快速、簡單、可靠。 HikariCP 是一個「零開銷」生產就緒的 JDBC 連線池。該庫大約 165Kb,非常輕量。在這裡閱讀我們如何做到這一點。
“簡單性是可靠性的先決條件。”
-埃茲格·迪傑斯特拉博士
重要的
為了避免池變為零且無法恢復的罕見情況,有必要配置TCP keepalive 。一些 JDBC 驅動程式透過屬性支援這一點,例如 PostgreSQL 上的tcpKeepAlive=true
,但無論如何,它也可以在作業系統層級進行設定。請參閱設定 OS TCP Keepalive 和/或 TCP keepalive 以獲得更好的 PostgreSQL 體驗。
Java 11+ Maven 神器:
< dependency >
< groupId >com.zaxxer</ groupId >
< artifactId >HikariCP</ artifactId >
< version >6.2.1</ version >
</ dependency >
Java 8 maven神器(維護模式):
< dependency >
< groupId >com.zaxxer</ groupId >
< artifactId >HikariCP</ artifactId >
< version >4.0.3</ version >
</ dependency >
Java 7 Maven神器(維護模式):
< dependency >
< groupId >com.zaxxer</ groupId >
< artifactId >HikariCP-java7</ artifactId >
< version >2.4.13</ version >
</ dependency >
Java 6 maven神器(維護模式):
< dependency >
< groupId >com.zaxxer</ groupId >
< artifactId >HikariCP-java6</ artifactId >
< version >2.3.13</ version >
</ dependency >
或從這裡下載。
創建微基準是為了使用 JMH 微基準框架隔離和測量池的開銷。您可以查看 HikariCP 基準測試項目以了解詳細信息,並自行查看/運行基準測試。
DataSource.getConnection()
/ Connection.close()
。Connection.prepareStatement()
、 Statement.execute()
、 Statement.close()
。與其他池相比,與獨特的「尖峰需求」負載相關的 HikariCP v2.6 分析。
客戶的環境要求獲得新連線的成本很高,並且需要動態大小的池,但還需要對請求峰值的回應能力。在此閱讀有關峰值需求處理的資訊。
又稱為「您可能不了解連線池大小」 。觀看 Oracle 實際效能小組的視頻,了解為什麼資料庫連線不需要像平常那麼多。事實上,過多的連結會對表現產生明顯且明顯的負面影響; Oracle 演示的情況下有 50 倍的差異。請繼續閱讀以找出答案。
我們要感謝 WIX 的工作人員在他們的工程部落格上主動撰寫了有關 HikariCP 的深入文章。有時間的話看一下。
閱讀我們有趣的“資料庫關閉”池挑戰。
像 HikariCP 這樣的開源軟體,像任何產品一樣,在自由市場中競爭。我們明白了。我們知道,產品的進步一旦公開,通常會被採納。我們知道,想法可以源自於時代精神;同時且獨立。但創新的時間表,特別是在開源專案中,也很明確,我們希望我們的用戶了解我們領域的創新流程的方向。看到數百個小時的思考和研究的結果如此輕易地被採用可能會令人士氣低落,這也許是自由市場所固有的,但我們並沒有士氣低落。我們充滿動力;以拉開差距。
HikariCP 具有合理的預設設置,無需額外調整即可在大多數部署中表現良好。除了下面標記的「必需品」之外,每個屬性都是可選的。
? HikariCP 對所有時間值都使用毫秒。
HikariCP 依靠精確的計時器來實現效能和可靠性。您的伺服器必須與時間來源(例如 NTP 伺服器)同步。特別是當您的伺服器在虛擬機器中運行時。為什麼?在這裡閱讀更多內容。不要依賴虛擬機器管理程式設定來「同步」虛擬機器的時鐘。配置虛擬機器內部的時間來源同步。如果您就因缺乏時間同步而導致的問題尋求支持,您將在 Twitter 上受到公開嘲笑。
? dataSourceClassName
這是 JDBC 驅動程式提供的DataSource
類別的名稱。請查閱特定 JDBC 驅動程式的文件以取得此類名稱,或請參閱下表。注意 不支援 XA 資料來源。 XA 需要一個真正的事務管理器,例如 bitronix。請注意,如果您使用jdbcUrl
進行「老式」基於 DriverManager 的 JDBC 驅動程式配置,則不需要此屬性。預設值:無
- 或者 -
? jdbcUrl
此屬性指示 HikariCP 使用「基於 DriverManager」的配置。我們認為基於資料來源的配置(上面)由於多種原因(見下文)更優越,但對於許多部署來說幾乎沒有顯著差異。當將此屬性與「舊」驅動程式一起使用時,您可能還需要設定driverClassName
屬性,但首先嘗試不設定。請注意,如果使用此屬性,您仍然可以使用DataSource屬性來配置驅動程序,實際上建議使用該屬性,而不是在 URL 本身中指定的驅動程式參數。預設值:無
? username
此屬性設定從底層驅動程式取得連線時所使用的預設驗證使用者名稱。請注意,對於 DataSource,這透過在底層 DataSource 上呼叫DataSource.getConnection(*username*, password)
以非常確定的方式運作。但是,對於基於驅動程式的配置,每個驅動程式都是不同的。在基於驅動程式的情況下,HikariCP 將使用此username
屬性在傳遞給驅動程式的DriverManager.getConnection(jdbcUrl, props)
呼叫的Properties
中設定user
屬性。如果這不是您所需要的,請完全跳過此方法並呼叫addDataSourceProperty("username", ...)
等。預設值:無
? password
此屬性設定從底層驅動程式取得連線時所使用的預設驗證密碼。請注意,對於 DataSource,這透過在底層 DataSource 上呼叫DataSource.getConnection(username, *password*)
以非常確定的方式運作。但是,對於基於驅動程式的配置,每個驅動程式都是不同的。在基於驅動程式的情況下,HikariCP 將使用此password
屬性在傳遞給驅動程式的DriverManager.getConnection(jdbcUrl, props)
呼叫的Properties
中設定password
屬性。如果這不是您所需要的,請完全跳過此方法並呼叫addDataSourceProperty("pass", ...)
等。預設值:無
✅ autoCommit
此屬性控制從池傳回的連線的預設自動提交行為。它是一個布林值。預設值:true
⏳ connectionTimeout
此屬性控制客戶端(即您)等待來自池的連線的最大毫秒數。如果超過此時間而沒有可用連接,則會拋出 SQLException。可接受的最低連線逾時為 250 毫秒。預設值:30000(30 秒)
⏳ idleTimeout
此屬性控制允許連線在池中空閒的最長時間。此設定僅在minimumIdle
定義為小於maximumPoolSize
時適用。一旦池達到minimumIdle
連線數,空閒連線就不會被終止。連線是否因空閒而退出,最大變化為 +30 秒,平均變化為 +15 秒。在此逾時之前,連線永遠不會因空閒而退出。值 0 表示永遠不會從池中刪除空閒連線。允許的最小值為 10000 毫秒(10 秒)。預設值:600000(10 分鐘)
⏳ keepaliveTime
此屬性控制 HikariCP 嘗試保持連線活動的頻率,以防止資料庫或網路基礎架構逾時。值必須小於maxLifetime
值。 「保持活動」只會發生在空閒連線上。當針對給定連線的「保持連線」時間到達時,該連線將從池中刪除、「ping」,然後返回池中。 「ping」是以下之一:呼叫 JDBC4 isValid()
方法或執行connectionTestQuery
。通常,池外的持續時間應以個位數毫秒甚至亞毫秒為單位進行測量,因此應該很少或沒有明顯的性能影響。允許的最小值為 30000 毫秒(30 秒),但分鐘範圍內的值是最理想的。預設值:120000(2 分鐘)
⏳ maxLifetime
此屬性控制池中連接的最長生命週期。正在使用的連接永遠不會退休,只有當它關閉時才會被刪除。在逐一連接的基礎上,應用較小的負衰減以避免池中的大規模滅絕。我們強烈建議設定此值,它應該比任何資料庫或基礎設施施加的連接時間限制短幾秒鐘。值 0 表示沒有最大生命週期(無限生命週期),當然取決於idleTimeout
設定。允許的最小值為 30000 毫秒(30 秒)。預設值:1800000(30 分鐘)
? connectionTestQuery
如果您的驅動程式支援 JDBC4,我們強烈建議不要設定此屬性。這適用於不支援 JDBC4 Connection.isValid() API
「舊版」驅動程式。這是在從池中向您提供連接之前執行的查詢,以驗證與資料庫的連接是否仍然有效。再次嘗試在沒有此屬性的情況下運行池,如果您的驅動程式不相容 JDBC4,HikariCP 將記錄錯誤來通知您。預設值:無
? minimumIdle
此屬性控制 HikariCP 嘗試在池中維護的最小空閒連線數。如果空閒連線低於此值且池中的總連線數小於maximumPoolSize
,HikariCP 將盡最大努力快速有效地新增其他連線。但是,為了獲得最大效能和對高峰需求的回應能力,我們建議不要設定此值,而是允許 HikariCP 充當固定大小的連接池。預設值:與 MaximumPoolSize 相同
? maximumPoolSize
此屬性控制池允許達到的最大大小,包括空閒連線和正在使用的連線。基本上這個值將決定到資料庫後端的實際連接的最大數量。合理的值最好由您的執行環境決定。當池達到此大小且沒有可用的空閒連線時,對 getConnection() 的呼叫將在逾時之前阻塞長達connectionTimeout
毫秒。請閱讀有關池大小的資訊。預設值:10
? metricRegistry
此屬性只能透過程式配置或 IoC 容器使用。此屬性可讓您指定池中使用的Codahale/Dropwizard MetricRegistry
實例來記錄各種指標。有關詳細信息,請參閱 Metrics wiki 頁面。預設值:無
? healthCheckRegistry
此屬性只能透過程式配置或 IoC 容器使用。此屬性可讓您指定池中使用的Codahale/Dropwizard HealthCheckRegistry
執行個體來報告目前運作狀況資訊。有關詳細信息,請參閱健康檢查 wiki 頁面。預設值:無
? poolName
此屬性表示連線池的使用者定義名稱,主要出現在日誌記錄和 JMX 管理控制台中,用於識別池和池配置。預設:自動生成
⏳ initializationFailTimeout
此屬性控制如果池無法成功使用初始連線進行播種,則池是否會「快速失敗」。任何正數都被視為嘗試取得初始連線的毫秒數;在此期間應用程式線程將被阻塞。如果在此逾時之前無法取得連接,則會拋出例外狀況。此逾時在connectionTimeout
期限之後套用。如果該值為零 (0),HikariCP 將嘗試取得並驗證連線。如果獲得連線但驗證失敗,則會拋出異常且池不會啟動。但是,如果無法獲取連接,池將啟動,但稍後獲取連接的努力可能會失敗。小於零的值將繞過任何初始連線嘗試,並且池將在嘗試在背景取得連線時立即啟動。因此,稍後獲取連接的努力可能會失敗。預設值:1
❎ isolateInternalQueries
此屬性決定 HikariCP 是否在自己的交易中隔離內部池查詢,例如連線活動測試。由於這些通常是唯讀查詢,因此很少需要將它們封裝在自己的事務中。僅當停用autoCommit
時此屬性才適用。預設值:假
❎ allowPoolSuspension
此屬性控制是否可以透過 JMX 暫停和恢復池。這對於某些故障轉移自動化場景很有用。當池暫停時,對getConnection()
呼叫不會逾時,並將一直保持到池恢復為止。預設值:假
❎ readOnly
此屬性控制從池中取得的連線預設是否處於唯讀模式。請注意,某些資料庫不支援唯讀模式的概念,而其他資料庫則在連線設定為唯讀時提供查詢最佳化。您是否需要此屬性在很大程度上取決於您的應用程式和資料庫。預設值:假
❎ registerMbeans
此屬性控制是否註冊 JMX 管理 Bean(“MBean”)。預設值:假
? catalog
此屬性設定支援目錄概念的資料庫的預設目錄。如果未指定此屬性,則使用 JDBC 驅動程式定義的預設目錄。預設值:驅動程式預設值
? connectionInitSql
此屬性設定一條 SQL 語句,該語句將在每次建立新連線後執行,然後將其新增至池中。如果此 SQL 無效或拋出異常,則將被視為連線失敗並遵循標準重試邏輯。預設值:無
? driverClassName
HikariCP 將嘗試僅根據jdbcUrl
透過 DriverManager 解析驅動程序,但對於某些較舊的驅動程序,也必須指定driverClassName
。除非您收到表明未找到驅動程式的明顯錯誤訊息,否則請忽略此屬性。預設值:無
? transactionIsolation
此屬性控制從池傳回的連線的預設交易隔離等級。如果未指定此屬性,則使用 JDBC 驅動程式定義的預設交易隔離等級。僅當您有所有查詢通用的特定隔離要求時才使用此屬性。此屬性的值是Connection
類別中的常數名稱,例如TRANSACTION_READ_COMMITTED
、 TRANSACTION_REPEATABLE_READ
等。
⏳ validationTimeout
此屬性控制測試連線活動性的最長時間。該值必須小於connectionTimeout
。可接受的最低驗證逾時為 250 毫秒。預設值:5000
⏳ leakDetectionThreshold
此屬性控制在記錄指示可能的連線洩漏的訊息之前連接可以脫離池的時間量。值 0 表示洩漏偵測已停用。啟用洩漏偵測的最低可接受值為 2000(2 秒)。預設值:0
➡ dataSource
此屬性只能透過程式配置或 IoC 容器使用。此屬性可讓您直接設定要由池包裝的DataSource
實例,而不是讓 HikariCP 透過反射來建構它。這在某些依賴注入框架中非常有用。指定此屬性後, dataSourceClassName
屬性和所有特定於 DataSource 的屬性將被忽略。預設值:無
? schema
此屬性設定支援模式概念的資料庫的預設模式。如果未指定此屬性,則使用 JDBC 驅動程式定義的預設架構。預設值:驅動程式預設值
➡ threadFactory
此屬性只能透過程式配置或 IoC 容器使用。此屬性允許您設定java.util.concurrent.ThreadFactory
的實例,該實例將用於建立池使用的所有執行緒。在一些受限的執行環境中需要它,在這些環境中執行緒只能透過應用程式容器提供的ThreadFactory
建立。預設值:無
➡ scheduledExecutor
此屬性只能透過程式配置或 IoC 容器使用。此屬性可讓您設定將用於各種內部規劃任務的java.util.concurrent.ScheduledExecutorService
的實例。如果為 HikariCP 提供ScheduledThreadPoolExecutor
實例,建議使用setRemoveOnCancelPolicy(true)
。預設值:無
➡ exceptionOverride
此屬性只能透過程式配置或 IoC 容器使用。此屬性允許您設定類別的實例,實作com.zaxxer.hikari.SQLExceptionOverride
接口,該介面將在由於特定異常情況而從池中逐出連接之前調用。通常,當拋出SQLException
時,如果存在特定的SQLStates或ErrorCodes,連線就會從池中逐出。將對SQLExceptionOverride
實例呼叫adjudicate()
方法,該方法可能傳回以下之一: Override.CONTINUE_EVICT
。 Override.DO_NOT_EVICT
或Override.MUST_EVICT
。除非在非常特殊的情況下,否則應該返回Override.CONTINUE_EVICT
,從而允許執行預設的逐出/不逐出邏輯。預設值:無
? exceptionOverrideClassName
此屬性可讓您指定實作com.zaxxer.hikari.SQLExceptionOverride
介面的使用者提供的類別的名稱。該類別的實例將由池實例化以裁定連接驅逐。有關完整說明,請參閱上面的exceptionOverride
屬性。預設值:無
正如您在上面看到的那樣,HikariCP 有很多可以轉動的“旋鈕”,但比其他一些池相對較少。這是一種設計理念。 HikariCP的設計美學是極簡主義。為了符合簡單即更好或少即是多的設計理念,一些配置軸被故意省略。
許多連接池,包括 Apache DBCP、Vibur、c3p0 等都提供PreparedStatement
快取。 HikariCP 沒有。為什麼?
在連線池層, PreparedStatements
只能針對每個連線進行快取。如果您的應用程式有 250 個常用執行的查詢和一個包含 20 個連接的池,那麼您會要求資料庫保存 5000 個查詢執行計劃——同樣,池必須快取這麼多的PreparedStatements
及其相關的物件圖。
大多數主要資料庫 JDBC 驅動程式都已經具有可設定的語句緩存,包括 PostgreSQL、Oracle、Derby、MySQL、DB2 等。 JDBC 驅動程式在利用資料庫特定功能方面處於獨特的地位,並且幾乎所有快取實作都能夠跨連接共用執行計劃。這意味著,您的 250 個常用查詢會在資料庫中產生 250 個執行計劃,而不是記憶體中的 5000 個語句和關聯的執行計劃。聰明的實作甚至不會在驅動程式層級的記憶體中保留PreparedStatement
對象,而只是將新實例附加到現有的計劃ID。
在池層使用語句快取是一種反模式,與驅動程式提供的快取相比,會對應用程式效能產生負面影響。
與語句快取一樣,大多數主要資料庫供應商都透過自己的驅動程式的屬性支援語句日誌記錄。這包括 Oracle、MySQL、Derby、MSSQL 等。有些甚至支援慢速查詢日誌記錄。對於那些不支援它的少數資料庫,有多種選擇。我們收到了一份報告,表明 p6spy 運作良好,並且還注意到 log4jdbc 和 jdbcdslog-exp 的可用性。
請閱讀《快速復原指南》,以了解如何設定驅動程式和系統以便從資料庫重新啟動和網路分割區事件中正確復原的詳細資訊。
您可以像這樣使用HikariConfig
類別1 :
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 );
1 MySQL 特定範例,請勿逐字複製。
或直接實例化HikariDataSource
,如下所示:
HikariDataSource ds = new HikariDataSource ();
ds . setJdbcUrl ( "jdbc:mysql://localhost:3306/simpsons" );
ds . setUsername ( "bart" );
ds . setPassword ( "51mp50n" );
...
或基於屬性檔:
// Examines both filesystem and classpath for .properties file
HikariConfig config = new HikariConfig ( "/some/path/hikari.properties" );
HikariDataSource ds = new HikariDataSource ( config );
屬性檔案範例:
dataSourceClassName =org.postgresql.ds.PGSimpleDataSource
dataSource.user =test
dataSource.password =test
dataSource.databaseName =mydb
dataSource.portNumber =5432
dataSource.serverName =localhost
或基於java.util.Properties
:
Properties props = new Properties ();
props . setProperty ( "dataSourceClassName" , "org.postgresql.ds.PGSimpleDataSource" );
props . setProperty ( "dataSource.user" , "test" );
props . setProperty ( "dataSource.password" , "test" );
props . setProperty ( "dataSource.databaseName" , "mydb" );
props . put ( "dataSource.logWriter" , new PrintWriter ( System . out ));
HikariConfig config = new HikariConfig ( props );
HikariDataSource ds = new HikariDataSource ( config );
還有一個可用的系統屬性hikaricp.configurationFile
,可用來指定屬性檔案的位置。如果您打算使用此選項,請使用預設建構函式HikariConfig
或HikariDataSource
實例,然後將載入屬性檔。
MySQL 效能技巧
我們建議使用dataSourceClassName
而不是jdbcUrl
,但兩者都可以接受。我們再說一遍,兩者都可以接受。
注意:Spring Boot自動配置用戶,需要使用基於jdbcUrl
的配置。
已知 MySQL 資料來源在網路逾時支援方面存在問題。請改用jdbcUrl
配置。
以下是流行資料庫的 JDBC DataSource類別的清單:
資料庫 | 司機 | 資料來源類 |
---|---|---|
阿帕契德比 | 德比 | org.apache.derby.jdbc.ClientDataSource |
火鳥 | 松鴉鳥 | org.firebirdsql.ds.FBSimpleDataSource |
谷歌扳手 | 扳手 | com.google.cloud.spanner.jdbc.JdbcDriver |
氫2 | 氫2 | org.h2.jdbcx.JdbcDataSource |
HSQL資料庫 | HSQL資料庫 | org.hsqldb.jdbc.JDBCDataSource |
IBM DB2 | IBM JCC | com.ibm.db2.jcc.DB2SimpleDataSource |
IBM Informix | IBM Informix | com.informix.jdbcx.IfxDataSource |
微軟SQL伺服器 | 微軟 | com.microsoft.sqlserver.jdbc.SQLServerDataSource |
連接器/J | ||
瑪麗亞資料庫 | 瑪麗亞資料庫 | org.mariadb.jdbc.MariaDbDataSource |
甲骨文 | 甲骨文 | oracle.jdbc.pool.OracleDataSource |
東方資料庫 | 東方資料庫 | com.orienttechnologies.orient.jdbc.OrientDataSource |
PostgreSQL | pgjdbc-ng | com.impossibl.postgres.jdbc.PGDataSource |
PostgreSQL | PostgreSQL | org.postgresql.ds.PGSimpleDataSource |
SAP 最大資料庫 | 樹液 | com.sap.dbtech.jdbc.DriverSapDB |
SQLite | 序列 | org.sqlite.SQLiteDataSource |
系統資料庫 | jConnect | com.sybase.jdbc4.jdbc.SybDataSource |
注意 Play 2.4 現在預設使用 HikariCP。 Play 框架推出了一個新插件;玩-hikaricp。如果您使用優秀的 Play 框架,那麼您的應用程式值得 HikariCP。感謝教育團隊!
tomekw 創建了一個新的 Clojure 包裝器,可以在此處找到。
tomekw 創建了一個新的 JRuby 包裝器,可以在此處找到。
Google 討論小組 HikariCP 在這裡,不斷增長的常見問題。
不要忘記 Wiki 來獲取更多信息,例如:
⇒ Java 8+(Java 6/7 工件處於維護模式)
⇒ slf4j 庫
高性能專案永遠不會有太多的工具!我們要感謝以下公司:
感謝 ej-technologies 提供的出色的一體化分析器 JProfiler。
YourKit 透過其全功能的 Java Profiler 支援開源專案。點擊下面的 YourKit 標誌以了解更多資訊。
請執行變更並從dev
分支而不是master
提交拉取請求。請將您的編輯器設定為使用空格而不是製表符,並遵循您正在編輯的程式碼的外觀風格。如果您希望生活在邊緣,那麼dev
分支總是比master
分支更「最新」。