快速、简单、可靠。 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
分支更“最新”。