HiKariCP是數據庫連接池的一個后起之秀。號稱性能最好。能夠完美地PK掉其它連接池。
什么?不是有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的……哈哈。
幾個連接池的代碼量對照(代碼量越少。一般意味着運行效率越高、發生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處理數據庫中斷的情況,評分例如以下:

說得這么好。用起來會不會非常麻煩啊。會不會有非常多參數要配置才干有這種效果啊?答案是:不會。
假設之前用的是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"