HikariCP


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又來了):

 

英文:

   constrained 不舒服的,被強迫的,拘泥的;

 

這個圖,也間接地、再一次地證明了boneCP比c3p0強大很多,當然,跟“光”比起來,又弱了不少啊。
 
那么,這么好的CP是怎么做到的呢?官網詳細地說明了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處理數據庫中斷的情況,評分如下:
 
 
==================================
======連接池配置=====

使用方法:

you can use the HikariConfig class like so:

HikariConfig config = new HikariConfig(); config.setJdbcUrl("jdbc:mysql://localhost:3306/simpsons"); config.setUsername("bart"); config.setPassword("51mp50n"); config.addDataSourceProperty("cachePrepStmts", "true"); config.addDataSourceProperty("prepStmtCacheSize", "250"); config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048"); HikariDataSource ds = new HikariDataSource(config);

or directly instantiate a HikariDataSource like so:

HikariDataSource ds = new HikariDataSource(); ds.setJdbcUrl("jdbc:mysql://localhost:3306/simpsons"); ds.setUsername("bart"); ds.setPassword("51mp50n"); ...

or property file based:

HikariConfig config = new HikariConfig("some/path/hikari.properties"); HikariDataSource ds = new HikariDataSource(config);

Example property file:

dataSourceClassName=org.postgresql.ds.PGSimpleDataSource
dataSource.user=test dataSource.password=test dataSource.databaseName=mydb dataSource.portNumber=5432 dataSource.serverName=localhost
 
 
=========== HiKariCP的數據源配置 ====================
 
 
 
[html]  view plain  copy
 
  1. <!-- Hikari Datasource -->  
  2. <bean id="dataSourceHikari" class="com.zaxxer.hikari.HikariDataSource"  destroy-method="shutdown">  
  3.  <!-- <property name="driverClassName" value="${db.driverClass}" /> --> <!-- 無需指定,除非系統無法自動識別 -->  
  4.  <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8" />  
  5.  <property name="username" value="${db.username}" />  
  6.  <property name="password" value="${db.password}" />  
  7.   <!-- 連接只讀數據庫時配置為true, 保證安全 -->  
  8.  <property name="readOnly" value="false" />  
  9.  <!-- 等待連接池分配連接的最大時長(毫秒),超過這個時長還沒可用的連接則發生SQLException, 缺省:30秒 -->  
  10.  <property name="connectionTimeout" value="30000" />  
  11.  <!-- 一個連接idle狀態的最大時長(毫秒),超時則被釋放(retired),缺省:10分鍾 -->  
  12.  <property name="idleTimeout" value="600000" />  
  13.  <!-- 一個連接的生命時長(毫秒),超時而且沒被使用則被釋放(retired),缺省:30分鍾,建議設置比數據庫超時時長少30秒,參考MySQL wait_timeout參數(show variables like '%timeout%';) -->  
  14.  <property name="maxLifetime" value="1800000" />  
  15.  <!-- 連接池中允許的最大連接數。缺省值:10;推薦的公式:((core_count * 2) + effective_spindle_count) -->  
  16.  <property name="maximumPoolSize" value="15" />  
  17. </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"
 
 
===============

下載地址及依賴環境

======================

1 下載地址

http://mvnrepository.com/artifact/com.zaxxer/HikariCP

2 Git主頁

https://github.com/brettwooldridge/HikariCP

3 依賴包

log4j-1.2.16.jar

slf4j-api-1.5.10.jar

slf4j-log4j12-1.5.10.jar

4 版本支持

Java 7 and Java 8 maven artifact:

    <dependency> <groupId>com.zaxxer</groupId> <artifactId>HikariCP</artifactId> <version>2.4.5</version> </dependency>

Java 6 maven artifact (maintenance mode):

    <dependency> <groupId>com.zaxxer</groupId> <artifactId>HikariCP-java6</artifactId> <version>2.3.13</version> </dependency>
=====================================

What do “Connection Cycle ops/ms” and “Statement Cycle ops/ms” mean in the context of a microbenchmark of a connection pool?

    In the context of a pool, we're trying to measure just the speed of pool operations -- so a "no-op" DataSource is used that does not perform actually connections or SQL. Connection Cycles measures how fast a connection can be obtained from the pool and then returned. Basically, this:

Connection conn = dataSource.getConnection();
conn.close();

Where dataSource is a HikariDataSource (pool) and conn.close() actually returns the Connection to the pool instead of closing the underlying DB Connection.

The Statement Cycle benchmark performs:

Statement statement = connection.createStatement();
statement.execute();
statement.close();

Because connection pools wrap Statement (and it's subclasses) with proxies, and track them so that they can be closed when the Connection is closed, there is overhead associated with both tracking the Statement and invoking against it. This micro-benchmark measures both.

 
=====================================
============ 連接池比對 ============
=====================================

proxool 更新時間截止2008年。速度可以,穩定性稍差,發較高的情況下會出錯。

c3p0 太古老,代碼及其復雜,不利於維護。貌似都比它強。

dbcp 是 apache 上的一個 java 連接池項目,也是 tomcat 使用的連接池組件。

druid 功能比較全面,且擴展性較好,比較方便對jdbc接口進行監控跟蹤等。

BoneCP 13年前最快的連接池項目。2013年后不再更新,心灰意冷。

HikariCP 光連接池

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM