zoukankan      html  css  js  c++  java
  • 为什么HikariCP被号称为性能最好的Java数据库连接池,如何配置使用

    转自:https://blog.csdn.net/clementad/article/details/46928621 

    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的数据源配置:

    <!-- BoneCp Datasource -->
     <bean id="dataSourceBoneCp" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close">
      <property name="driverClass" value="${db.driverClass}" />
      <property name="jdbcUrl" value="${db.url}" />
      <property name="username" value="${db.username}" />
      <property name="password" value="${db.password}" />
      <property name="idleConnectionTestPeriodInMinutes" value="2" />
      <property name="idleMaxAgeInMinutes" value="2" />
      <property name="maxConnectionsPerPartition" value="2" />
      <property name="minConnectionsPerPartition" value="0" />
      <property name="partitionCount" value="2" />
      <property name="acquireIncrement" value="1" />
      <property name="statementsCacheSize" value="100" />
      <property name="lazyInit" value="true"/>
      <property name="maxConnectionAgeInSeconds" value="20"/>
      <property name="defaultReadOnly" value="true"/>
     </bean>

    HiKariCP的数据源配置:

    <!-- Hikari Datasource -->
     <bean id="dataSourceHikari" class="com.zaxxer.hikari.HikariDataSource"  destroy-method="shutdown">
      <!-- <property name="driverClassName" value="${db.driverClass}" /> --> <!-- 无需指定,除非系统无法自动识别 -->
      <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8" />
      <property name="username" value="${db.username}" />
      <property name="password" value="${db.password}" />
       <!-- 连接只读数据库时配置为true, 保证安全 -->
      <property name="readOnly" value="false" />
      <!-- 等待连接池分配连接的最大时长(毫秒),超过这个时长还没可用的连接则发生SQLException, 缺省:30秒 -->
      <property name="connectionTimeout" value="30000" />
      <!-- 一个连接idle状态的最大时长(毫秒),超时则被释放(retired),缺省:10分钟 -->
      <property name="idleTimeout" value="600000" />
      <!-- 一个连接的生命时长(毫秒),超时而且没被使用则被释放(retired),缺省:30分钟,建议设置比数据库超时时长少30秒,参考MySQL wait_timeout参数(show variables like '%timeout%';) -->
      <property name="maxLifetime" value="1800000" />
      <!-- 连接池中允许的最大连接数。缺省值:10;推荐的公式:((core_count * 2) + effective_spindle_count) -->
      <property name="maximumPoolSize" value="15" />
     </bean>

    其中,很多配置都使用缺省值就行了,除了maxLifetime和maximumPoolSize要注意自己计算一下。
    其他的配置(sqlSessionFactory、MyBatis MapperScannerConfigurer、transactionManager等)统统不用变。

    其他关于Datasource配置参数的建议:
    Configure your HikariCP idleTimeout and maxLifeTime settings to be one minute less than the wait_timeout of MySQL.
    对于有Java连接池的系统,建议MySQL的wait_timeout使用缺省的8小时(http://www.rackspace.com/knowledge_center/article/how-to-change-the-mysql-timeout-on-a-server)。

    另外:对于web项目,记得要配置:destroy-method="shutdown"

  • 相关阅读:
    html 上传图片前预览
    php获取当月天数及当月第一天及最后一天、上月第一天及最后一天实现方法
    php 计算 pdf文件页数
    php 获取半年内每个月的订单数量, 总价, 月份
    php 获取两个数组之间不同的值
    小程序支付功能
    关于nginx的Job for nginx.service failed because the control process exited with error code.错误
    linux 安装 Apollo
    MongoDB待续。。。
    ABP vNext...待续
  • 原文地址:https://www.cnblogs.com/panchanggui/p/10405244.html
Copyright © 2011-2022 走看看