为什么HikariCP被号称为性能最好的Java数据库连接池,如何配置使用

为什么HikariCP被号称为性能最好的Java数据库连接池,如何配置使用,第1张

HiKariCP是数据库连接池的一个后起之秀,号称性能最好,可以完美地PK掉其他连接池

为何要使用HiKariCP?这要先从BoneCP说起:

什么?不是有C3P0/DBCP这些成熟的数据库连接池吗?一直用的好好的,为什么又搞出一个BoneCP来?因为,传说中BoneCP在快速这个特点上做到了极致,官方数据是C3P0等的25倍左右。不相信?其实我也不怎么信。可是,有图有真相啊(图片来自BoneCP官网:http://jolbox.com/benchmarks.html):

而且,网上对于BoneCP是好评如潮啊,推荐的文章一搜一大堆。

然而,上Maven Repository网站(http://mvnrepository.com/artifact/com.jolbox/bonecp)查找有没有最新版本的时候,你会发现最新的是2013年10月份的(这么久没新版本出来了?)。于是,再去BoneCP的Githut(https://github.com/wwadge/bonecp)上看看最近有没有提交代码。却发现,BoneCP的作者对于这个项目貌似已经心灰意冷,说是要让步给HikariCP了(有图有真相):

……什么?又来一个CP?……什么是Hikari?

Hikari来自日文,是“光”(阳光的光,不是光秃秃的光)的意思。作者估计是为了借助这个词来暗示这个CP速度飞快。不知作者是不是日本人,不过日本也有很多优秀的码农,听说比特币据说日本人搞出来的。。。

这个产品的口号是“快速、简单、可靠”。实际情况跟这个口号真的匹配吗?又是有图有真相(Benchmarks又来了):

这个图,也间接地、再一次地证明了boneCP比c3p0强大很多,当然,跟“光”比起来,又弱了不少啊。

那么,这么好的P是怎么做到的呢?官网详细地说明了HikariCP所做的一些优化,总结如下:

字节码精简:优化代码,直到编译后的字节码最少,这样,CPU缓存可以加载更多的程序代码;

优化代理和拦截器:减少代码,例如HikariCP的Statement proxy只有100行代码,只有BoneCP的十分之一;

自定义数组类型(FastStatementList)代替ArrayList:避免每次get()调用都要进行range check,避免调用remove()时的从头到尾的扫描;

自定义集合类型(ConcurrentBag):提高并发读写的效率;

其他针对BoneCP缺陷的优化,比如对于耗时超过一个CPU时间片的方法调用的研究(但没说具体怎么优化)。

很多优化的对比都是针对BoneCP的……哈哈。

(参考文章:https://github.com/brettwooldridge/HikariCP/wiki/Down-the-Rabbit-Hole)

几个连接池的代码量对比(代码量越少,一般意味着执行效率越高、发生bug的可能性越低):

可是,“黄婆卖瓜,自催自擂”这个俗语日本人也是懂得,于是,用户的好评如潮也是有图有真相:

还有第三方关于速度的测试:

也许你会说,速度高,如果不稳定也是硬伤啊。于是,关于稳定性的图也来了:

另外,关于可靠性方面,也是有实验和数据支持的。对于数据库连接中断的情况,通过测试getConnection(),各种CP的不相同处理方法如下:

(所有CP都配置了跟connectionTimeout类似的参数为5秒钟)

HikariCP:等待5秒钟后,如果连接还是没有恢复,则抛出一个SQLExceptions 异常;后续的getConnection()也是一样处理;

C3P0:完全没有反应,没有提示,也不会在“CheckoutTimeout”配置的时长超时后有任何通知给调用者;然后等待2分钟后终于醒来了,返回一个error;

Tomcat:返回一个connection,然后……调用者如果利用这个无效的connection执行SQL语句……结果可想而知;大约55秒之后终于醒来了,这时候的getConnection()终于可以返回一个error,但没有等待参数配置的5秒钟,而是立即返回error;

BoneCP:跟Tomcat的处理方法一样;也是大约55秒之后才醒来,有了正常的反应,并且终于会等待5秒钟之后返回error了;

可见,HikariCP的处理方式是最合理的。根据这个测试结果,对于各个CP处理数据库中断的情况,评分如下:

参考文章:https://github.com/brettwooldridge/HikariCP/wiki/Bad-Behavior:-Handling-Database-Down

说得这么好,用起来会不会很麻烦啊,会不会有很多参数要配置才能有这样的效果啊?答案是:不会。

如果之前用的是BoneCP配置的数据源,那么,就简单了,只需要把dataSource换一下,稍微调整一下参数就行了:

BoneCP的数据源配置:

<!--BoneCpDatasource-->

<beanid="dataSourceBoneCp"class="com.jolbox.bonecp.BoneCPDataSource"destroy-method="close">

<propertyname="driverClass"value="${db.driverClass}"/>

<propertyname="jdbcUrl"value="${db.url}"/>

<propertyname="username"value="${db.username}"/>

<propertyname="password"value="${db.password}"/>

<propertyname="idleConnectionTestPeriodInMinutes"value="2"/>

<propertyname="idleMaxAgeInMinutes"value="2"/>

<propertyname="maxConnectionsPerPartition"value="2"/>

<propertyname="minConnectionsPerPartition"value="0"/>

<propertyname="partitionCount"value="2"/>

<propertyname="acquireIncrement"value="1"/>

<propertyname="statementsCacheSize"value="100"/>

<propertyname="lazyInit"value="true"/>

<propertyname="maxConnectionAgeInSeconds"value="20"/>

<propertyname="defaultReadOnly"value="true"/>

</bean>

HiKariCP的数据源配置:

<!--HikariDatasource-->

<beanid="dataSourceHikari"class="com.zaxxer.hikari.HikariDataSource"destroy-method="shutdown">

<!--<propertyname="driverClassName"value="${db.driverClass}"/>--><!--无需指定,除非系统无法自动识别-->

<propertyname="jdbcUrl"value="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8"/>

<propertyname="username"value="${db.username}"/>

<propertyname="password"value="${db.password}"/>

<!--连接只读数据库时配置为true,保证安全-->

<propertyname="readOnly"value="false"/>

<!--等待连接池分配连接的最大时长(毫秒),超过这个时长还没可用的连接则发生SQLException,缺省:30秒-->

<propertyname="connectionTimeout"value="30000"/>

<!--一个连接idle状态的最大时长(毫秒),超时则被释放(retired),缺省:10分钟-->

<propertyname="idleTimeout"value="600000"/>

<!--一个连接的生命时长(毫秒),超时而且没被使用则被释放(retired),缺省:30分钟,建议设置比数据库超时时长少30秒,参考MySQLwait_timeout参数(showvariableslike'%timeout%')-->

<propertyname="maxLifetime"value="1800000"/>

<!--连接池中允许的最大连接数。缺省值:10;推荐的公式:((core_count*2)+effective_spindle_count)-->

<propertyname="maximumPoolSize"value="15"/>

</bean>

其中,很多配置都使用缺省值就行了,除了maxLifetime和maximumPoolSize要注意自己计算一下。

其他的配置(sqlSessionFactory、MyBatis MapperScannerConfigurer、transactionManager等)统统不用变。

其他关于Datasource配置参数的建议:

Configure your HikariCPidleTimeoutandmaxLifeTimesettings to be one minute less than thewait_timeoutof MySQL.

连接先建立一些连接,并且这些连接允许共享,因此这样就节省了每次连接的时间开销。Mysql数据库为例,连接池在Tomcat中的配置与使用。

1、创建数据库Student,表student

2、配置server.xml文件。Tomcat安装目录下conf中server.xml文件。

<GlobalNamingResources>

<Resource

name="jdbc/DBPool"

type="javax.sql.DataSource"

password=""

driverClassName="com.mysql.jdbc.Driver"

maxIdle="2"

maxWait="5000"

username="root"

url="jdbc:mysql://localhost:3306/student"

maxActive="3"

/>

</GlobalNamingResources>

name:指定连接池的名称

type:指定连接池的类,他负责连接池的事务处理

url:指定要连接的数据库

driverClassName:指定连接数据库使用的驱动程序

username:数据库用户名

password:数据库密码

maxWait:指定最大建立连接等待时间,如果超过此时间将接到异常

maxIdle:指定连接池中连接的最大空闲数

maxActive:指定连接池最大连接数

3、配置web.xml文件。

<web-app>

<resource-ref>

<description>mysql数据库连接池配置</description>

<res-ref-name>jdbc/DBPool</res-ref-name>

<res-type>javax.sql.DataSource</res-type>

<res-auth>Container</res-auth>

<res-sharing-scope>Shareable</res-sharing-scope>

</resource-ref>

</web-app>

4、配置context.xml文件

与server.xml文件所在的位置相同。

<Context>

<ResourceLink

name="jdbc/DBPool"

type="javax.sql.DataSource"

global="jdbc/DBPool"

/>

</Context>

5、测试

DataSource pool = null

Context env = null

Connection conn = null

Statement st = null

ResultSet rs = null

try{

env = (Context)new InitialContext().lookup("java:comp/env")

//检索指定的对象,返回此上下文的一个新实例

pool = (DataSource)env.lookup("jdbc/DBPool")

//获得数据库连接池

if(pool==null){out.printl("找不到指定的连接池!")}

con = pool.getConnection()

st = con.createStatement()

rs = st.executeQuery("select * from student")

}catch(Exception ex){out.printl(ne.toString())}

数据库连接池的主要 *** 作如下:

(1)建立数据库连接池对象(服务器启动)。

(2)按照事先指定的参数创建初始数量的数据库连接(即:空闲连接数)。

(3)对于一个数据库访问请求,直接从连接池中得到一个连接。如果数据库连接池对象中没有空闲的连接,且连接数没有达到最大(即:最大活跃连接数),创建一个新的数据库连接。

(4)存取数据库。

(5)关闭数据库,释放所有数据库连接(此时的关闭数据库连接,并非真正关闭,而是将其放入空闲队列中。如实际空闲连接数大于初始空闲连接数则释放连接)。

(6)释放数据库连接池对象(服务器停止、维护期间,释放数据库连接池对象,并释放所有连接)。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/9926129.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-03
下一篇 2023-05-03

发表评论

登录后才能评论

评论列表(0条)

保存