什么是HikariCP
HikariCP是数据库连接池的一个后起之秀,号称性能最好,可以完美地PK掉其他连接池。是一个高性能的JDBC连接池,基于BoneCP做了不少的改进和优化。超快,快到连Spring Boot2都宣布支持了。
官方 GitHub 地址 https://github.com/brettwooldridge/HikariCP
什么是BoneCP
传说中BoneCP在快速这个特点上做到了极致,官方数据是C3P0等的25倍左右,以下为性能测试报告。
单线程
1,000,000获取连接/释放连接请求
获取/释放连接之间没有延迟
连接池范围:20-50
增量:5·
线程:1
分区:1
多线程
- 500 个线程分别获取释放 100 个连接
- 在获取连接和释放连接之间引入了 10ms 的延迟 Thread.sleep(),模拟连接完成工作
- 连接池范围:50-200
- 增量:5
- 线程:5
Prepared Statement
- 500 个线程分别获取释放 100 个连接
- 无延迟
- 连接池范围:50-200
- 增量:5
- 线程:5
为什么需要 HikariCP
BoneCP 作者放弃维护,并在 Github 项目主页推荐大家使用 HikariCP,Hikari(ひかり[shi ga li]) 来自日文,是 光 的意思。这个产品的口号是 快速、简单、可靠
优化
- 字节码精简 : 优化代码,直到编译后的字节码最少,这样,CPU 缓存可以加载更多的程序代码
- 优化代理和拦截器 : 减少代码,例如 HikariCP 的 Statement proxy 只有 100 行代码,只有 BoneCP 的十分之一
- 自定义数组类型(FastStatementList)代替 ArrayList : 避免每次 get() 调用都要进行 range check,避免调用 remove() 时的从头到尾的扫描
- 自定义集合类型(ConcurrentBag): 提高并发读写的效率
- 其他针对 BoneCP 缺陷的优化: 比如对于耗时超过一个 CPU 时间片的方法调用的研究(但没说具体怎么优化)
代码量
几个连接池的代码量对比(代码量越少,一般意味着执行效率越高、发生 BUG 的可能性越低)
Pool | Files | Code |
---|---|---|
Vibur | 34 | 1927 |
HikariCP | 21 | 2228 |
Tomcat | 31 | 6345 |
BoneCP | 49 | 7293 |
C3P0 | 120 | 15550 |
速度
稳定性
可靠性
另外,关于可靠性方面,也是有实验和数据支持的。对于数据库连接中断的情况,通过测试getconnection(),各种CP的不相同处理方法如下(所有CP都配置了跟connectionTimeout类似的参数为5秒钟)
- HikaricP(A):等待5秒钟后,如果连接还是没有恢复,则抛出一个SQLExceptions异常;后续的getconnection()也是一样处理
- C3PO(C-):完全没有反应,没有提示,也不会在checkoutTimeout 配置的时长超时后有任何通知给调用者;然后等待2分钟后终于醒来了,返回一个error
- Tomcat(F):返回一个connection,然后调用者如果利用这个无效的connection执行SQL语句结果可想而知;大约55秒之后终于醒来了,这时候的getconnection()终于可以返回一个error,但没有等待参数配置的5秒钟,而是立即返回 error
BoneCP(C):跟Tomcat的处理方法一样;也是大约55秒之后才醒来,有了正常的反应,并且终于会等待5秒钟之后返回 error了
整合Hikaricp
POM
```xml
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>${hikaricp.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
<exclusions>
<exclusion> <groupId>org.apache.tomcat</groupId> <artifactId>tomcat-jdbc</artifactId> </exclusion> </exclusions> </dependency> <!-- MYSQL驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency>
添加配置:application.yml
```properties
server:
port: 8082
spring:
application:
name: hello-spring-boot
thymeleaf:
cache: false
mode: HTML
encoding: UTF-8
servlet:
content-type: text/html
datasource:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/test?useSSL=true&serverTimezone=GMT&allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8
username: root
password: root
hikari:
minimum-idle: 5
idle-timeout: 600000
maximum-pool-size: 10
auto-commit: true
pool-name: MyHikariCP
max-lifetime: 1800000
connection-timeout: 30000
connection-test-query: SELECT 1