【转载】Spring Boot数据库连接池Hikari
Spring Boot数据库连接池Hikari
Hikari 介绍
Hikari, 日语中"光"的发音。
HikariCP是一个高性能的Java数据库连接池,被广泛应用于Java开发领域。它是目前最快和最轻量级的连接池之一,具有出色的性能和可靠性。数据库连接池是一个提高程序与数据库的连接的优化,连接池它主要作用是提高性能、节省资源、控制连接数、连接管理等操作。
以下是HikariCP的一些主要特点和优势:
高性能:HikariCP通过使用异步和非阻塞的方式,以及一些性能优化的技术,实现了卓越的连接获取和释放性能。它具有非常低的延迟和高吞吐量,能够处理大量并发的数据库请求。
轻量级:HikariCP的代码库非常小,只有几百KB大小,不依赖大量的外部库和复杂的依赖关系。这使得它在内存消耗和加载时间方面表现优秀,适合于资源受限的环境和快速启动的应用程序。
自动化管理:HikariCP具有自动化管理连接池的功能。它可以根据应用程序的需求动态调整连接数,并自动管理连接的生命周期,包括创建、验证、超时处理和关闭等操作。这减少了开发人员对连接池的手动管理工作。
配置灵活:HikariCP提供丰富的可配置选项,可以根据应用程序的需求进行调整。它支持连接池的最大连接数、最小空闲连接数、连接超时时间、连接验证等多种配置参数。
兼容性:HikariCP与大多数主流的JDBC框架和数据库引擎兼容,无缝集成于Spring框架、Hibernate、MyBatis等。它可以与各种数据库(如MySQL、PostgreSQL、Oracle、SQL Server等)进行集成。
总之,HikariCP是一个高性能、轻量级、自动化管理和灵活配置的Java数据库连接池。它通过优化连接获取和释放过程,提供卓越的性能和可靠性,是开发高效、可扩展和高并发的Java应用程序的理想选择。
配置 Hikari
HikariCP, 如其名,性能像光一样快。在Spring Boot中配置HikariCP作为数据库连接池非常简单。
添加HikariCP的依赖。在项目的pom.xml文件中添加HikariCP的依赖,如下所示:
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>3.4.5</version>
</dependency>
由于Springboot2.0默认就是使用的Hikari连接池,所以无需额外添加Hikari相关的maven依赖。

只需要在application.properties或application.yml文件中配置HikariCP的属性。
以下是一个示例配置:
application.properties文件:
# 数据库连接配置
#必要配置
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
# mysql8驱动 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&zeroDateTimeBehavior=convertToNull
spring.datasource.username=
spring.datasource.password=
# HikariCP连接池配置
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
# 设置连接池中保持的最小空闲连接数,默认为10
spring.datasource.hikari.minimum-idle=10
# 设置连接池中允许的最大连接数,默认为10
spring.datasource.hikari.maximum-pool-size=10
# 设置是否自动提交事务,默认为true
spring.datasource.hikari.auto-commit=true
# 设置连接在连接池中保持空闲的最长时间,默认为600000(10分钟),单位是毫秒
spring.datasource.hikari.idle-timeout=60000
# 设置连接池的名称,默认为"HikariPool-1"
spring.datasource.hikari.pool-name=HikariPool-1
# 设置连接在连接池中允许存在的最长时间,默认为1800000(30分钟),单位是毫秒
spring.datasource.hikari.max-lifetime=1800000
# 设置获取数据库连接的超时时间,默认为30000(30秒),单位是毫秒
spring.datasource.hikari.connection-timeout=30000
# 设置用于测试连接的SQL查询语句
spring.datasource.hikari.connection-test-query=SELECT 1
# 设置连接验证的超时时间,默认为5000(5秒),单位是秒
spring.datasource.hikari.validation-timeout=5000
#不常用配置
spring.datasource.hikari.metric-registry= #允许使用的Codahale/Dropwizard 实例MetricRegistry来记录各种指标
spring.datasource.hikari.health-check-registry= #允许使用的Codahale/Dropwizard 的实例HealthCheckRegistry来报告当前的健康信息。
spring.datasource.hikari.initialization-fail-timeout= #连接失败时尝试时间
spring.datasource.hikari.isolate-internal-queries= #是否在其自己的事务中隔离内部池查询。该属性仅适用于autoCommit禁用的情况。 默认值:false
spring.datasource.hikari.allow-pool-suspension= #是否可以通过JMX暂停和恢复。默认值:false
spring.datasource.hikari.read-only= #获取的连接是否处于只读模式。默认值:false
spring.datasource.hikari.register-mbeans= #是否注册JMX管理Bean(“MBeans”)。 默认值:false
spring.datasource.hikari.catalog= #设置默认目录为支持目录的概念数据库。默认:驱动程序默认
spring.datasource.hikari.connection-init-sql= #每个新连接创建后,将其添加到池中之前执行该语句。默认值:无
spring.datasource.hikari.driver-class-name= #较老的驱动程序还必须指定。默认值:无
spring.datasource.hikari.transaction-isolation= #从池返回的连接的默认事务隔离级别。默认:驱动程序指定。
spring.datasource.hikari.validation-timeout= #连接测试活动的最长时间。默认值:5000
spring.datasource.hikari.leak-detection-threshold= #连接泄漏检测。默认值:0
spring.datasource.hikari.dataSource= #直接设置DataSource池的实例,而不是通过反射来构造。 默认值:无
spring.datasource.hikari.schema= #设置的默认模式。默认:驱动程序默认
spring.datasource.hikari.threadFactory= #设置用于创建池使用的所有线程的实例。 默认值:无
spring.datasource.hikari.scheduledExecutor= #设置用于各种内部计划任务的实例。默认值:无
application.yml文件:
# 数据库连接配置
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb
username: username
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.zaxxer.hikari.HikariDataSource
hikari:
# 设置是否自动提交事务,默认为true
auto-commit: true
# 设置用于测试连接的SQL查询语句
connection-test-query: SELECT 1
# 设置获取数据库连接的超时时间,默认为30秒,单位是毫秒
connection-timeout: 30000
# 设置连接在连接池中保持空闲的最长时间,默认为10分钟,单位是毫秒
idle-timeout: 30000
# 设置连接在连接池中允许存在的最长时间,默认为30分钟,单位是毫秒
max-lifetime: 1800000
# 设置连接池中允许的最大连接数,默认为10
maximum-pool-size: 10
# 设置连接池中保持的最小空闲连接数,默认为10
minimum-idle: 10
# 设置连接池的名称,默认为"HikariPool-1"
pool-name: HikariPool-1
# 设置连接验证的超时时间,默认为5000(5秒),单位是毫秒
validation-timeout: 5000
Hikari配置详解
| 配置项 | 案例值 | 描述 |
| autoCommit | true | 是否自动提交。默认是 true,自动提交从池中返回的连接。 |
| connectionTimeout | 30000 | 客户端创建连接等待超时时间,如果30秒内没有获取连接则抛异常,不再继续等待。等待来自池的连接的最大毫秒数,默认为 30000 ms = 30 s,允许最小时间是 250 毫秒,如果小于 250 毫秒,则被重置回 30 秒。 |
| idleTimeout | 60000 | 连接允许最长空闲时间,如果连接空闲时间超过1分钟,则会被关闭。连接允许在池中闲置的最长时间,默认为 60000,即 10 分钟。如果 idleTimeout + 1 秒 > maxLifetime 且 maxLifetime > 0,则会被重置为 0(代表永远不会退出);如果 idleTimeout != 0 且小于 10 秒,则会被重置为 10 秒。只有当 minimumIdle 小于 maximumPoolSize 时,这个参数才生效,当空闲连接数超过 minimumIdle,而且空闲时间超过 idleTimeout,则会被移除。 |
| maxLifetime | 1800000 | 连接最长生命周期,当连接存活时间达到30分钟之后会被关闭作退休处理。池中连接最长生命周期。默认为 1800000,如果不等于 0 且小于 30 秒则会被重置回 30 分钟。强烈建议设置这个参数。 |
| minimumIdle | 1 | 连接池中最小空闲连接数。控制连接池空闲连接的最小数量,当连接池空闲连接少于 minimumIdle,而且总共连接数不大于 maximumPoolSize 时,HikariCP 会尽力补充新的连接。为了性能考虑,不建议设置此值,而是让 HikariCP 把连接池当做固定大小的处理,默认 minimumIdle 与 maximumPoolSize 一样。当 minIdle < 0 或者 minIdle > maxPoolSize,则被重置为 maxPoolSize,该值默认为 10。 |
| maximumPoolSize | 10 | 连接池中最大连接数。池中最大连接数,包括闲置和使用中的连接。默认为 10。如果 maxPoolSize 小于1,则会被重置。当 minIdle <=0 被重置为DEFAULT_POOL_SIZE 则为 10;如果 minIdle > 0 则重置为 minIdle 的值。 |
| readOnly | false | 从池中获取的连接是否是只读模式。从池中获取的连接是否默认处于只读模式。默认为 false。这个属性工作与否取决于数据库的实现。 |
| poolName | HikariPool-1 | 连接池的用户定义名称,主要出现在日志记录和 JMX 管理控制台中以识别池和池配置。默认为 HikariPool-1。 |
| connectionTestQuery | 如果你的驱动程序支持 JDBC4,我们强烈建议不要设置这个属性。这是针对不支持 JDBC4 Connection.isValid() API的 "传统 "驱动程序。这是一个查询,在一个连接从池子里给你之前会被执行,以验证与数据库的连接是否仍然有效。同样,尝试在没有这个属性的情况下运行数据库池,如果你的驱动不符合JDBC4标准,HikariCP 会记录一个错误,让你知道。默认值:无。 | |
| validationTimeout | 5000 | 测试连接是否空闲的间隔 |
| leadDetectionThreshold | 60000 | 连接被占用的超时时间,超过1分钟客户端没有释放连接则强制回收该连接,防止连接泄漏 |
| keepaliveTime | 0 | 连接存活时间,这个值必须小于 maxLifetime 值。Keepalive "只会发生在空闲的连接上。当对一个给定的连接进行 "keepalive "的时间到了,该连接将从池中移除。允许的最小值是 30000 ms(30秒),但最理想的值是在分钟范围内。默认值:0 |
除过基本基本配置外,搬运一下比较关键常用的配置,也方便我日后查找。
https://github.com/brettwooldridge/HikariCP#configuration-knobs-baby
- autoCommit
此属性控制从池返回的连接的默认自动提交行为。默认值:真 - connectionTimeout
此属性控制客户端等待来自池的连接的最大毫秒数。如果在没有连接可用的情况下超过此时间,则将抛出 SQLException。可接受的最低连接超时时间为 250 毫秒。默认值:30000(30 秒) - idleTimeout
此属性控制允许连接在池中闲置的最长时间。此设置仅在minimumIdle
定义为小于时适用maximumPoolSize。一旦池达到连接, 空闲连接将不会被取消minimumIdle。连接是否以空闲状态退役,最大变化为 +30 秒,平均变化为 +15 秒。在此超时*之前,*连接永远不会因空闲而退出。值 0 表示永远不会从池中删除空闲连接。允许的最小值为 10000 毫秒(10 秒)。默认值:600000(10 分钟) - keepaliveTime
此属性控制 HikariCP 尝试保持连接活动的频率,以防止它被数据库或网络基础设施超时。该值必须小于该 maxLifetime值。“keepalive”只会发生在空闲连接上。当针对给定连接进行“保持连接”的时间到了时,该连接将从池中删除、“ping”,然后返回到池中。'ping' 是其中之一:调用 JDBC4isValid()
方法,或执行 connectionTestQuery. 通常,池外的持续时间应该以个位数毫秒甚至亚毫秒为单位进行测量,因此应该几乎没有或没有明显的性能影响。最小允许值为 30000 毫秒(30 秒), 默认值:0(禁用 - 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
重点解释一下这几个配置项:
maxLifetime
了解这个值的作用前,先了解一下mysqlwait_timeout的作用:mysql 为了防止空闲连接浪费,占用资源,在超过wait_timeout 时间后,会主动关闭该连接,清理资源。
通过以下语句, 可以查看mysql 具体配置的时间
show variables like 'wait_timeout%'
默认是28800s,也就是8小时。
也就是说,mysql发现某个连接超过8小时还有没有任何请求,就会自动断开,但是hikaricp如何知道我池子里维护的一把连接,有没有被mysql回收呢?
所以就有了maxLifetime这个配置,官方也强烈建议必须按需设置此值!自然这个值也应该小于mysql的wait_timeout。
如果先不考虑idleTimeout配置,那hikaricp在空闲连接超过maxLifetime,就会从连接池中剔除,防止业务进程取到了已关闭的连接,导致业务受损。
keepaliveTime & connectionTestQuery
最开始没太理解,后来类比tcp的keepAlive机制,就清楚多了。
他的作用还是如上所说,为了防止获取到被mysql关闭的无效连接,导致业务出错的一种兜底扫描方案。
具体过程呢,就是每隔keepaliveTime时间间隔,去和数据库发送心跳,来探测连接是否有效。如果发现是无效的,就会及时从连接池中剔除,来保证业务进程获取到的都是有效连接。
如果你配置了connectionTestQuery,如"select 1", 心跳检查过程就会调用connectionTestQuery。
所以如果你配置了connectionTestQuery(exsample: select 1),但是没有配置keepaliveTime,是没有用的,因为默认是关闭的。
而connectionTestQuery配置项,官方建议如果驱动支持JDBC4,不要设置此属性!
因为相比于通过select查询方式探活,mysql 自带的ping命令(目测应该就是TCP的ping),性能更高(直接在sql server返回结果,就不会做语法解析,执行优化,再通过存储引擎操作)
而基本上java mysql驱动包5以上的版本都支持JDBC4。

maximumPoolSize
数据源连接池最大连接数,其实就是线程池中队列的大小。默认大小为10
minimumIdle
空闲连接数最大值,默认大小和maximumPoolSize的默认值一样,也是10。
在hikaricp pool创建时,会启动一个HouseKeeper定时任务,每隔30s,判断空闲线程数低于minimumIdle,并且当前线程池总连接数小于maximumPoolSize,就建立和mysql的一个长连接,然后加入到连接池中。
官方建议minimumIdle和maximumPoolSize保持一致,这和jvm的xms,xmx参数也建议保持一致有类似的考量。
因为hikaricp的HouseKeeper在发现idleTimeout>0 并且 minimumIdle < maximumPoolSize时,先会去扫描一遍需要移除空闲连接,和mysql断开连接。然后再一次性补满空闲连接数至到minimumIdle。
mysql的一次连接就是3次握手,断开就是4次挥手,所以这个过程在实际生产中可能会相当耗时,自然会影响业务请求的处理响应。
idleTimeout
这是hikaricp用来判断是否应该从连接池移除空闲连接的一个重要的配置。负责剔除的也还是HouseKeeper这个定时任务,值为0时,HouseKeeper不会移除空闲连接,直到到达maxLifetime后,才会移除,默认值也就是0。
正常情况下,HouseKeeper会找到所有状态为空闲的连接队列,遍历一遍,将空闲超时到达idleTimeout且未超过minimumIdle数量的连接的批量移除。
只有掌握了这些配置的真正含义后,才能减少埋坑,不过坑防不胜防,还有以下两点需要注意:
一:检查相关配置,确保不要业务进程获取到已经关闭连接
hikaricp为了防止业务进程获取到已经关闭失效的连接,煞费苦心。
除了HouseKeeper定时任务30s一扫,来移除失效连接外。
还有maxLifetime的兜底移除失效连接。
但,坑也就在这,HouseKeeper的扫描移除条件是:
idleTimeout > && minimumIdle < maximumPoolSize
所以,如果你minimumIdle = maximumPoolSize,那就意味着,一定要检查确保maxLifetime 一定要小于实际mysql的wait_timeout值。
连接池的大小越大越好吗?
关于这个问题,hikaricp的作者也是很头疼,
这老哥真的无语,我都默认值是10了,你们哪怕可以别设置这个值,非得几十个人用的系统,配成100的大小。
另外,他甚至专门开了个页面来讲这个问题:
https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing

里面有 Oracle 关于连接池大小的性能测试视频,感兴趣的可以看看。
总结来说,影响数据库瓶颈主要是: CPU, 磁盘 和网络。
根据这些因素,作者给出了一个计算公式
连接数 = ((cpu核数 * 2) + 磁盘有效主轴数)
此外,作者还解释了,默认值为啥是10:正常情况下,10个连接,就能够撑起6000TPS的简单查询 !!!
原文地址:
更多推荐
所有评论(0)