Hikari是一款非常强大,高效,并且号称“史上最快连接池”。并且在springboot2.0之后,采用的默认数据库连接池就是Hikari。不需要引入依赖,已经在SpringBoot中包含了。
 GitHub地址:https://github.com/brettwooldridge/HikariCP


参考链接:https://heapdump.cn/article/2613255

生产参数配置

  1. spring:
  2. datasource:
  3. driver-class-name: com.mysql.jdbc.Driver
  4. type: com.zaxxer.hikari.HikariDataSource
  5. url: jdbc:mysql://mysql-cluster:13306/invx?useUnicode=true&characterEncoding=utf8&useSSL=false&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
  6. username: root
  7. password: Hacloud@2020!
  8. hikari:
  9. poolName: Hikari
  10. #此属性控制从池返回的连接的默认自动提交行为,默认值:true
  11. auto-commit: true
  12. #最小空闲连接数量
  13. minimum-idle: 10
  14. #连接池最大连接数,默认是10
  15. maximum-pool-size: 1000
  16. #空闲连接存活最大时间,默认600000(10分钟)
  17. idle-timeout: 600000
  18. #连接的生命时长(毫秒),超时而且没被使用则被释放(retired),默认:30分钟 1800000ms
  19. max-lifetime: 1800000
  20. #等待连接池分配连接的最大时长(毫秒),超过这个时长还没可用的连接则发生SQLException, 默认:30秒
  21. connection-timeout: 300000
  22. #数据库连接超时时间,默认30秒,即30000
  23. #连接测试语句
  24. connection-test-query: SELECT 1
  25. data-source-properties:
  26. #在每个连接中缓存的语句的数量。默认值为保守值25。建议将其设置为250-500之间
  27. prepStmtCacheSize: 300
  28. #缓存的已准备SQL语句的最大长度,默认值是256,但是往往这个长度不够用
  29. prepStmtCacheSqlLimit: 2048
  30. #缓存开关,如果这里设置为false,上面两个参数都不生效
  31. cachePrepStmts: true
  32. #较新版本的 MySQL 支持服务器端准备好的语句,这可以提供实质性的性能提升
  33. useServerPrepStmts: true

参考配置

Hikari号称最快的连接池,这边贴一个github上找到的一个宣称最大化MySQL性能的配置文件(db.properties),供各位看官查看

  1. #inner
  2. jdbcUrl=jdbc:mysql://192.168.2.7:3306/lxd?useSSL=false
  3. username=root
  4. password=root
  5. #pool properties
  6. connectionTimeout=60000
  7. idleTimeout=600000
  8. minimumIdle=1
  9. maximumPoolSize=50
  10. #poolname
  11. #datasource properties, max performance
  12. #该项极大影响插入效率
  13. dataSource.cachePrepStmts=true
  14. dataSource.prepStmtCacheSize=250
  15. dataSource.prepStmtCacheSqlLimit=2048
  16. dataSource.useServerPrepStmts=true
  17. dataSource.useLocalSessionState=true
  18. dataSource.rewriteBatchedStatements=true
  19. dataSource.cacheResultSetMetadata=true
  20. #dataSource.cacheServerConfiguration=true
  21. #dataSource.elideSetAutoCommits=true
  22. dataSource.maintainTimeStats=false
  23. dataSource.useCursorFetch=true
  1. # 数据库配置
  2. spring:
  3. datasource:
  4. type: com.zaxxer.hikari.HikariDataSource
  5. driverClassName: com.mysql.jdbc.Driver
  6. url: jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=utf-8&useSSL=false
  7. username: root
  8. password: root
  9. # Hikari 连接池配置
  10. # 最小空闲连接数量
  11. hikari:
  12. minimum-idle: 5
  13. # 空闲连接存活最大时间,默认600000(10分钟)
  14. idle-timeout: 180000
  15. # 连接池最大连接数,默认是10
  16. maximum-pool-size: 10
  17. # 此属性控制从池返回的连接的默认自动提交行为,默认值:true
  18. auto-commit: true
  19. # 连接池名称
  20. pool-name: MyHikariCP
  21. # 此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认1800000即30分钟
  22. max-lifetime: 1800000
  23. # 数据库连接超时时间,默认30秒,即30000
  24. connection-timeout: 30000
  25. connection-test-query: SELECT 1
  1. # 文件上传配置
  2. spring:
  3. ## 数据库配置
  4. datasource:
  5. type: com.zaxxer.hikari.HikariDataSource
  6. driver-class-name: com.mysql.cj.jdbc.Driver
  7. url: jdbc:mysql://127.0.0.1:3306/hikari-cp?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&allowMultiQueries=true
  8. username: root
  9. password: root
  10. ## Hikari 连接池配置 ------ 详细配置请访问:https://github.com/brettwooldridge/HikariCP
  11. hikari:
  12. ## 最小空闲连接数量
  13. minimum-idle: 10
  14. ## 空闲连接存活最大时间,默认600000(10分钟)
  15. idle-timeout: 18000
  16. ## 连接池最大连接数,默认是10
  17. maximum-pool-size: 1000
  18. ## 此属性控制从池返回的连接的默认自动提交行为,默认值:true
  19. auto-commit: true
  20. ## 连接池母子
  21. pool-name: OfficialWebsiteHikariCP
  22. ## 此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认1800000即30分钟
  23. max-lifetime: 1800000
  24. ## 数据库连接超时时间,默认30秒,即30000
  25. connection-timeout: 300000
  26. connection-test-query: SELECT 1
  27. jpa:
  28. show-sql: true
  29. open-in-view: true
  30. jackson:
  31. default-property-inclusion: non_null
  32. logging:
  33. config: classpath:logback.xml
  1. # 配置数据源信息
  2. spring:
  3. datasource: # 数据源的相关配置
  4. type: com.zaxxer.hikari.HikariDataSource # 数据源类型:HikariCP
  5. driver-class-name: com.mysql.jdbc.Driver # mysql驱动
  6. url: jdbc:mysql://localhost:3306/foodie-dev?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true
  7. username: root
  8. password: 123456
  9. hikari:
  10. connection-timeout: 30000 # 等待连接池分配连接的最大时长(毫秒),超过这个时长还没可用的连接则发生SQLException, 默认:30秒
  11. minimum-idle: 5 # 最小连接数
  12. maximum-pool-size: 20 # 最大连接数
  13. auto-commit: true # 事务自动提交
  14. idle-timeout: 600000 # 连接超时的最大时长(毫秒),超时则被释放(retired),默认:10分钟
  15. pool-name: DateSourceHikariCP # 连接池名字
  16. max-lifetime: 1800000 # 连接的生命时长(毫秒),超时而且没被使用则被释放(retired),默认:30分钟 1800000ms
  17. connection-test-query: SELECT 1 # 连接测试语句
  18. # mybatis配置
  19. mybatis:
  20. type-aliases-package: com.lzp.pojo # 所有POJO类所在包路径
  21. mapper-locations: classpath:mapper/*.xml # mapper映射文件
  1. # 不同数据源这四个配置都会用到
  2. spring.datasource.url=jdbc:mysql://localhost:3306/test
  3. spring.datasource.username=root
  4. spring.datasource.password=123456
  5. spring.datasource.driver-class-name=com.mysql.jdbc.Driver
  6. #以下的配置项是hikari特有的配置
  7. # 等待连接池分配连接的最大时长(毫秒),超过这个时长还没可用的连接则发生SQLException, 默认:30秒
  8. spring.datasource.hikari.connection-timeout=30000
  9. # 最小连接数
  10. spring.datasource.hikari.minimum-idle=5
  11. # 最大连接数
  12. spring.datasource.hikari.maximum-pool-size=15
  13. # 自动提交
  14. spring.datasource.hikari.auto-commit=true
  15. # 一个连接idle状态的最大时长(毫秒),超时则被释放(retired),默认:10分钟
  16. spring.datasource.hikari.idle-timeout=600000
  17. # 连接池名字
  18. spring.datasource.hikari.pool-name=DatebookHikariCP
  19. # 一个连接的生命时长(毫秒),超时而且没被使用则被释放(retired),默认:30分钟 1800000ms,建议设置比数据库超时时长少60秒
  20. spring.datasource.hikari.max-lifetime=28740000
  21. spring.datasource.hikari.connection-test-query=SELECT 1
  22. #以下是针对MYSQL驱动的配置参数
  23. # 在每个连接中缓存的语句的数量。默认值为保守值25。建议将其设置为250-500之间
  24. spring.datasource.hikari.prepStmtCacheSize = 300
  25. # 缓存的已准备SQL语句的最大长度,默认值是256,但是往往这个长度不够用
  26. spring.datasource.hikari.prepStmtCacheSqlLimit = 2048
  27. # 缓存开关,如果这里设置为false,上面两个参数都不生效
  28. spring.datasource.hikari.cachePrepStmts = true
  29. #较新版本的 MySQL 支持服务器端准备好的语句,这可以提供实质性的性能提升
  30. spring.datasource.hikari.useServerPrepStmts = true

Hikari配置说明
image.png
image.png

HikariCP连接池配置详解

对应的配置属性、解释、注意点都来源于官方:[https://github.com/brettwooldridge/HikariCP]

注意点:
1)所有时间单位的属性都是毫秒。
2)属性分必须;频繁使用;非频繁使用三个级别,重要度由高到低

必须属性(Essentials)
1. dataSourceClassName or jdbcUrl
配置由 jdbc驱动提供的对应数据库 DataSource 类名,常见的如下表:

注意点:
⚠ 1)Note: Spring Boot auto-configuration users, you need to use jdbcUrl-based configuration. (使用spring boot自动化配置数据源的需要配置jdbcUrl,不能只配置dataSourceClassName)
⚠ 2)The MySQL DataSource is known to be broken with respect to network timeout support. Use jdbcUrl configuration instead.(MySQL数据库数据源在面对网络超时时有故障,所以也需要用jdbcUrl替代,所有上表中MySQL的行注释掉了)

jdbcUrl用来配置jdbc连接串,很多人习惯配置jdbcUrl 。注意:一些老的驱动还要同时配置 driverClassName,否则会报错(推荐不用配置它,可以先不配置尝试运行看报不报错)

dataSourceClassName 和 jdbcUrl缺省都是空。

最佳实践:鉴于使用spring-boot自动装配使用HikariCP的只配置jdbcUrl即可,driverClassName根据测试情况可选配置

  1. username
    很容易理解,就是当前用户名,缺省是空。 必须配置

  2. password
    指用户名对应的密码,缺省是空。必须配置

频繁使用的属性(Frequently used)

  1. autoCommit
    这个属性控制连接返回池中前auto-commit是否自动进行。缺省:true。
    最佳实践:不需要配置,保持缺省即可。

  2. connectionTimeout
    控制一个客户端等待从池中获取连接的最大时间。超过该时间还获取不到连接则抛出SQLException,最低可设置的时间是250ms,缺省:30000ms
    最佳实践:非特殊业务场景保持缺省30s连接超时即可。

  3. idleTimeout
    控制空闲连接的在池中最大的空闲时间。注意:这个配置只有当配置了minimumIdle属性(表示允许的最小空闲连接数),且比maximumPoolSize(表示池中允许的最大连接数)更小时才生效。 这个比较好理解:当前池中有空闲连接且比允许的最小空闲连接多时,根据空闲超时时间来逐出。

当配置为0时表示空闲连接永远不逐出。
缺省:600000ms
最小生效值:10000ms

连接池会定时轮询检测哪些连接是空闲,并且空闲达到了idleTimeout配置的时间,但轮询间隔有时间差,一个空闲连接最大可空闲idleTimeout + 30s会逐出,平均是:idleTimeout + 15s。
最佳实践:不设置该属性和minimumIdle属性,保持连接池固定的连接

  1. keepaliveTime
    用于跟数据库保持心跳连接,防止底层网络基础设施超时断开,定期验证连接的有效性。这个参数需要设置的比maxLifetime(连接最大生存时间,下文会介绍)小。只会对池中空闲连接发生keeplive,具体执行细节是:
    从池中取出一个连接,执行“ping”,成功后再放回。
    ping:
    如果当前支持JDBC4 , 通过调用isValid()方法实现
    否则执行connectionTestQuery属性(下文会介绍)指定的sql

这个参数配置后连接池会定期检测连接有效性,检测过程中连接短暂从池中移出,不过不用担心,耗时非常短(几ms甚至更短)

缺省:0, 即不开启
最小可配置:30000ms ,即30秒

最佳实践: 需要设置, 可设置为60000, 即1分钟心跳一次

  1. maxLifetime
    该属性用于控制连接在池中的最大生存时间,超过该时间强制逐出,连接池向数据申请新的连接进行补充。注意:当前正在使用的连接不会强制逐出,哪怕它的累计时间已经到了maxLifetime。

强烈建议设置该属性,可设置的比数据库或网络基础设施允许的最大连接时间小一些。 如数据库连接最大失效时间是8小时,可设置为4小时。

缺省:1800000, 即30min
最小可配置:30000,即30s

最佳实践:需要设置,根据数据库或网络基础设施的情况,比它们小一些

  1. connectionTestQuery
    如果当前连接驱动支持JDBC4, 强烈不建议设置此属性。因为该属性的设置是为了支持keepalive检测,只有当JDBC4的isValid不可用时才使用connectionTestQuery配置的sql进行检测;或者当从池中获取连接时检测连接是否有效

缺省:none

最佳实践:驱动支持JDBC4不需要设置,反之需要配置,MYSQL: select 1; Oracle: select 1 from dual

  1. minimumIdle
    配置连接池最小空闲连接数。为了性能最优化和为了应对高峰请求的快速响应强烈不建议设置该属性,让HikariCP连接池保持固定大小。
    缺省:跟maximumPoolSize相同

最佳实践:保持缺省,让连接池固定大小,避免扩缩容带来的性能影响

  1. maximumPoolSize
    配置允许连接池达到的最大连接数(包括空闲和正在使用的),当池中连接达到maximumPoolSize,且都不空闲,当有新请求从池中申请连接池会阻塞等待可用连接,达到connectionTimeout还不能申请成功,则抛出SQLException。

缺省:10

最佳实践:根据实际环境配置,通常设置为核心数的2倍较优

  1. metricRegistry
    配置该属性,能让连接池将度量信息收集起来供分析。配置的属性是Codahale/Dropwizard的实例,具体可参考wiki页面:https://github.com/brettwooldridge/HikariCP/wiki/Dropwizard-Metrics

  2. healthCheckRegistry
    同样是收集信息用,这个属性收集的是连接池的健康状况。配置的属性是Codahale/Dropwizard的实例,具体可参考wiki页面:https://github.com/brettwooldridge/HikariCP/wiki/Dropwizard-HealthChecks

总结
最佳的配置如下:

配置项 配置值 说明
jdbcUrl jdbc:mysql://ip:3306/db
username xx 数据库用户名
password xx 用户名对应密码
keepaliveTime 60000 一分钟检测一次连接有效性
maxLifetime 1500000 25分钟, 经调查我们数据库默认的超时时间是30min
connectionTestQuery select 1 不支持JDBC4驱动的需要配置
maximumPoolSize 8 CPU核心数的两倍

连接池连接数的设置

引入数据库连接池
数据库连接是有限的、昂贵的资源,一个数据库连接对象对应一个物理数据库的连接,如果每次数据库操作都创建新的连接,使用完后释放,会导致系统性能低下,这就引出了连接池的概念。

数据库连接池是负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,可以视作一个存放数据库连接的容器。

数据库连接池采用了资源池设计模式,用于资源共享,避免资源的频繁分配与释放问题。同时便于统一管理,可以通过对连接池的控制,限制系统与数据库的连接,监视数据库的连接数量和使用情况。

连接池的必要性
1、不使用连接池流程
下面以访问MySQL为例,执行一个SQL命令,如果不使用连接池,需要经过哪些流程。

不使用数据库连接池的步骤:

TCP建立连接的三次握手
MySQL认证的三次握手
真正的SQL执行
MySQL的关闭
TCP的四次握手关闭
可以看到,为了执行一条SQL,却多了非常多网络交互。
优点:实现简单
缺点:

网络IO较多
数据库的负载较高
响应时间较长及QPS较低
应用频繁的创建连接和关闭连接,导致临时对象较多,GC频繁
在关闭连接后,会出现大量TIME_WAIT 的TCP状态(在2个MSL之后关闭)
2、使用连接池流程
使用数据库连接池的步骤:

第一次访问的时候,需要建立连接。 但是之后的访问,均会复用之前创建的连接,直接执行SQL语句。
优点:

较少了网络开销
系统的性能会有一个实质的提升
没了麻烦的TIME_WAIT状态
数据库连接数设置
系统可采取设置最小连接数和最大连接数等参数来控制连接池中的连接。最小连接数是系统启动时创建的数据库连接数。最小连接数小,则启动快,响应慢。通常设置较大一些。最小连接数可以设置为5个-10个。最大连接数根据硬件配置设置,4核心机器可以设为10个,8核心可以设为20个。

HikariCP的默认的最大和最小连接数是10。作者建议是设置最大和最小连接数为相同的值,维护一个高性能连接池。

为什么连接池数并不是越大越好?
第一点,首先我们要知道单核CPU“同时”运行多个线程,只不过是假象。单核CPU同一时刻只能执行一个线程,然后操作系统切换上下文,CPU 核心快速调度,执行另一个线程的代码。这其中便涉及到了大量上下文切换带来的额外性能损耗。

第二点,由上可知,一个N核心服务器,设置数据库连接数为N便能提供最优性能。然而,实际情况会受到磁盘IO和网络IO的影响,在IO等待时间内,线程阻塞等待,CPU处于空闲状态。因此,在线程处理I/O密集业务操作时,需要设置线程/连接数比CPU大一些,以提高吞吐量。

连接数的计算公式

连接数 = ((核心数 2) + 有效磁盘数)
1
服务器 CPU 是 4核 i7 的,连接池大小应该为 ((4
2) + 1) = 9 ~ 10个。具体需要根据实际业务场景做调整。

业务场景

对于并发访问,可以采用小的数据库连接池,然后将剩下的业务线程放在队列中等待。
如果系统中混合了长事务和短事务,正确的做法应该是创建两个连接池,一个服务于长事务,一个服务于”实时”查询,也就是短事务。

hikariCP性能调优

最近项目做压力测试,发现hikari cp会报一些错误,优化排查花了不少时间。有同样问题的可以参考下
尽量配置固定大小的数据库连接池
maximum-pool-size:默认10,一般为 cpu数2+磁盘数+10(另外加的10保证服务载的时候连接不会被频繁recycle)
idle-timeout: 建议设置为0,pool设置为固定大小的连接池(大小取决于maximum-pool-size)保证每次都能直接在pool中拿到可以连接;
connection-timeout: 建议设置比数据库大一些
*max-life-time
: 建议设置比数据库小一些,保证池中的连接都是可用的;比如数据库设置30分钟,那么这里可以设置1740000L 毫秒=29分钟

  1. mysql> show variables like '%timeout%';
  2. +-----------------------------+----------+
  3. | Variable_name | Value |
  4. +-----------------------------+----------+
  5. | connect_timeout | 10 | hikari cp connectionTimeout
  6. | wait_timeout | 1800 | hikari cp maxLifeTime
  7. +-----------------------------+----------+

问题一:

Connection is not available, request timed out after xxxx ms
升级hikariCP版本不小于3.3.1