- 为什么使用连接池
短连接
短连接是指程序和数据库通信时需要建立连接,执行操作后,连接关闭。短连接简单来说就是每一次操作数据库,都要打开和关闭数据库连接,基本步骤是:连接→数据传输→关闭连接。
在慢速网络下使用短连接,连接的开销会很大;在生产繁忙的系统中,连接也可能会受到系统端口数的限制,如果要每秒建立几千个连接,那么连接断开后,端口不会被马上回收利用,必须经历一个 “FIN” 阶段的等待,直到可被回收利用为止,这样就可能会导致端口资源不够用。
长连接
长连接是指程序之间的连接在建立之后,就一直打开,被后续程序重用。使用长连接的初衷是减少连接的开销,尽管 MySQL 的连接比其他数据库要快得多。
对此,研发工程师、系统运维工程师、DBA 需要保持沟通,确定合理的连接策略,千万不要不假思索就采用长连接。
连接池
由于一些数据库创建和销毁连接的开销很大,或者相对于所执行的具体数据操作,连接所耗的资源过多,此时就可能需要添加连接池来改进性能。
数据库连接池是一些网络代理服务或应用服务器实现的特性,如 J2EE 服务器,它实现了一个持久连接的 “池”,允许其他程序、客户端来连接,这个连接池将被所有连接的客户端共享使用,连接池可以加速连接,也可以减少数据库连接,降低数据库服务器的负载。
- 链接池的选择
常用的主流开源数据库连接池有 C3P0,DBCP,Tomcat Jdbc Pool,BoneCP, Druid,HikariCP
HikariCP:https://github.com/brettwooldridge/HikariCP
Druid: https://github.com/alibaba/druid
为何要使用 HiKariCP?这要先从 BoneCP 说起:
什么?不是有 C3P0/DBCP 这些成熟的数据库连接池吗?一直用的好好的,为什么又搞出一个 BoneCP 来?因为,传说中 BoneCP 在快速这个特点上做到了极致,官方数据是 C3P0 等的 25 倍左右。
3 Druid 连接池配置
特点:https://github.com/alibaba/druid/wiki/Druid%E8%BF%9E%E6%8E%A5%E6%B1%A0%E4%BB%8B%E7%BB%8D
配置参数:https://github.com/alibaba/druid/wiki/DruidDataSource%E9%85%8D%E7%BD%AE
需要注意的点:
** (1). 根据业务的实际情况配置链接参数**
** (2). 链接回收问题**
<!-- 超过时间限制是否回收 -->
<property name=``"removeAbandoned"
value=``"true"``/>
<!-- 超时时间;单位为秒。``600``秒=``10``分钟 -->
<property name=``"removeAbandonedTimeout"
value=``"600"``/>
需要根据实际情况考虑是否需要开启此属性
** (3). 配置了 maxWait 导致的公平锁问题**
配置了 maxWait 之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置 useUnfairLock 属性为 true 使用非公平锁。
4.HikariCP 连接池配置
HiKariCP 是数据库连接池的一个后起之秀,号称性能最好,可以完美地 PK 掉其他连接池,是一个高性能的 JDBC 连接池,基于 BoneCP 做了不少的改进和优化。
并且在 SpringBoot2.0 之后已经默认将数据库连接池选择为了 HikariCP。
优势:
(1)字节码精简
优化代码,直到编译后的字节码最少,这样,CPU 缓存可以加载更多的程序代码;
(2)优化代理和拦截器
减少代码,例如 HikariCP 的 Statement proxy 只有 100 行代码,只有 BoneCP 的十分之一;
(3)自定义数组类型 (FasttList)代替 ArrayList
避免每次 get() 调用都要进行 range check, 避免调用 remove() 时的从头到尾的扫描;
(4)自定义集合类型
提高并发读写的效率
配置参数
https://github.com/brettwooldridge/HikariCP/wiki
默认配置
springboot 的 HikariDataSource 默认配置的默认值如下
name | 构造器默认值 | 默认配置 validate 之后的值 | validate 重置 |
---|---|---|---|
minIdle | -1 | 10 | minIdle<0 或者 minIdle>maxPoolSize, 则被重置为 maxPoolSize |
maxPoolSize | -1 | 10 | 如果 maxPoolSize 小于 1,则会被重置。当 minIdle<=0 被重置为 DEFAULT_POOL_SIZE 则为 10; 如果 minIdle>0 则重置为 minIdle 的值 |
maxLifetime | MINUTES.toMillis(30) = 1800000 | 1800000 | 如果不等于 0 且小于 30 秒则会被重置回 30 分钟 |
connectionTimeout | SECONDS.toMillis(30) = 30000 | 30000 | 如果小于 250 毫秒,则被重置回 30 秒 |
validationTimeout | SECONDS.toMillis(5) = 5000 | 5000 | 如果小于 250 毫秒,则会被重置回 5 秒 |
loginTimeout | 10 | 30 | Math.max(1, (int) MILLISECONDS.toSeconds(500L + connectionTimeout)),为 connectionTimeout+500ms 转为秒数取整 与 1 取最大者 |
idleTimeout | MINUTES.toMillis(10) = 600000 | 600000 | 如果 idleTimeout+1 秒 > maxLifetime 且 maxLifetime>0,则会被重置为 0;如果 idleTimeout!=0 且小于 10 秒,则会被重置为 10 秒 |
leakDetectionThreshold | 0 | 0 | 如果大于 0 且不是单元测试,则进一步判断:(leakDetectionThreshold < SECONDS.toMillis(2) or (leakDetectionThreshold > maxLifetime && maxLifetime > 0),会被重置为 0 . 即如果要生效则必须 > 0,而且不能小于 2 秒,而且当 maxLifetime > 0 时不能大于 maxLifetime |
initializationFailTimeout | 1 | 1 | - |
isAutoCommit | true | true | - |
isReadOnly | false | fasle | - |
isAllowPoolSuspension | false | false | - |
isIsolateInternalQueries | false | false | - |
isRegisterMbeans | false | false | - |
sealed | false | true | 运行启动后这个标志为 true,表示不再运行修改 |
poolName | null | HikariPool-1 | - |
catalog | null | null | - |
connectionInitSql | null | null | - |
connectionTestQuery | null | null | - |
dataSourceClassName | null | null | - |
schema | null | null | - |
transactionIsolationName | null | null | - |
dataSource | null | null | - |
dataSourceProperties | {} | {} | - |
threadFactory | null | null | - |
scheduledExecutor | null | null | - |
metricsTrackerFactory | null | null | - |
metricRegistry | null | null | - |
healthCheckRegistry | null | null | - |
healthCheckProperties | {} | {} | - |