Druid-数据库连接池
导言
Druid是阿里巴巴开源的数据库连接池实现,提供了强大的性能监控和扩展功能。被称为是目前最好的数据库连接池,尤其是它的功能、性能、扩展性
简介
比对
| 连接池 | 优点 | 缺点与常见瓶颈 |
|---|---|---|
| HikariCP | 性能最好,代码轻量,Spring Boot 2.x/3.x 默认;高并发下获取连接开销低。 | 监控能力较弱,没有 Druid 那种内置 Web 控制台;需要配合 Micrometer/Prometheus 做观测。 |
| Druid | 监控强,支持 SQL 统计、慢 SQL、连接泄漏检测、SQL 防火墙、密码加密;国内生态成熟。 | 功能多带来额外开销,高并发下通常略慢于 HikariCP;配置项较多,StatView 等组件要注意安全暴露。 |
| Tomcat JDBC Pool | 轻量,和 Tomcat 集成方便;支持异步获取连接。 | 性能一般,社区活跃度不如 HikariCP、Druid;功能也比较基础。 |
| DBCP2 | 老牌稳定,文档多,兼容性好。 | 性能较弱,高并发下锁竞争和对象包装开销明显;新项目不建议使用。 |
| C3P0 | 早期项目里常见,支持基础连接检测。 | 维护停滞,性能较差,配置复杂,存在潜在死锁风险;新项目应避开。 |
参数说明
Druid 关键参数说明
| 参数 | 建议值 | 说明 |
|---|---|---|
initial-size | 5-10 | 启动时初始化连接数,避免首次请求抖动。 |
min-idle | 5-10 | 保持一定预热连接,突发流量下响应更稳。 |
max-active | 20-100 | 最大活跃连接数。不要超过 MySQL max_connections 的合理比例。 |
max-wait | 3000-60000 | 获取连接最大等待时间。核心接口建议 3-5 秒,避免长时间阻塞。 |
test-while-idle | true | 空闲时检测连接有效性,比 testOnBorrow 性能更好。 |
time-between-eviction-runs-millis | 60000 | 空闲连接检测间隔,建议 1-5 分钟。 |
min-evictable-idle-time-millis | 300000 | 空闲超过该时间的连接可能被回收。 |
keep-alive | true | 开启保活,减少因网络中间设备断开空闲连接导致的报错。 |
filters: stat,wall | 建议开启 | stat 提供 SQL 监控,wall 提供 SQL 防火墙。 |
最佳实践
| 参数 | 作用 | 最佳实践 |
|---|---|---|
initialSize | 初始化时建立的物理连接数 | 建议与 minIdle 一致,避免冷启动抖动 |
minIdle | 最小空闲连接数 | 建议为 maxActive × 0.2 ~ 0.5,或 CPU 核数 × 1.5 |
maxActive | 最大活跃连接数 | 按 QPS 和 SQL 耗时计算,见下方公式 |
maxWait | 获取连接最大等待时间 | 建议 3000ms 左右,避免线程长期阻塞 |
testWhileIdle | 空闲时检测连接有效性 | 建议 true,配合 validationQuery 使用 |
testOnBorrow | 借连接时检测有效性 | 建议 false,高并发下性能损耗明显 |
testOnReturn | 还连接时检测有效性 | 建议 false |
validationQuery | 检测连接是否有效的 SQL | MySQL 用 SELECT 1 |
timeBetweenEvictionRunsMillis | 销毁线程检测间隔 | 建议 10000 ~ 60000ms |
minEvictableIdleTimeMillis | 空闲连接最小存活时间 | 建议 300000 ~ 1800000ms |
keepAlive | 对 minIdle 内连接保活 | 建议 true,版本需 ≥ 1.1.21 更稳定 |
keepAliveBetweenTimeMillis | 空闲多久执行保活检测 | 建议 30000 ~ 120000ms |
maxEvictableIdleTimeMillis | 连接最大存活时间 | 可设为 7 小时或根据 MySQL wait_timeout 调整 |
poolPreparedStatements | 是否缓存 PreparedStatement | MySQL 场景通常建议 false |
maxPoolPreparedStatementPerConnectionSize | 每个连接缓存 PS 数量 | 若开启 PSCache,可设为 10 ~ 20 |
filters | 扩展插件 | 常用 stat,wall,分别做监控和 SQL 防火墙 |
常用调优算法
maxActive ≈ (峰值QPS × 平均 SQL 耗时 ms) / 1000 × 1.2 ~ 1.5
minIdle ≈ maxActive × 0.2 ~ 0.5 minIdle ≈ CPU 核数 × 1.5
initialSize = minIdle
参数作用范围
| 参数类别 | 作用域 | 说明 |
|---|---|---|
initialSize / minIdle / maxActive | 连接池级别 | 控制整个数据源的连接容量 |
maxWait | 连接池级别 | 控制获取连接时的等待超时 |
testWhileIdle / testOnBorrow / testOnReturn | 连接池级别 | 控制何时检测连接有效性 |
validationQuery | 连接池级别 | 所有检测都共用这条 SQL |
timeBetweenEvictionRunsMillis | 连接池级别 | 销毁线程按这个间隔扫描整个池 |
minEvictableIdleTimeMillis / maxEvictableIdleTimeMillis | 连接池级别 | 决定空闲连接是否被回收 |
keepAlive / keepAliveBetweenTimeMillis | 连接池级别 | 对 minIdle 内连接做保活检测 |
poolPreparedStatements | 连接池级别 | 控制是否开启 PSCache |
maxPoolPreparedStatementPerConnectionSize | 每个物理连接级别 | 限制单个连接缓存的 PreparedStatement 数量 |
filters | 数据源级别 | 对整个数据源的连接和 SQL 生效 |
推荐示例组合
spring: datasource: type: com.alibaba.druid.pool.DruidDataSource druid: initial-size: 5 min-idle: 10 max-active: 50 max-wait: 3000 validation-query: SELECT 1 test-while-idle: true test-on-borrow: false test-on-return: false time-between-eviction-runs-millis: 60000 min-evictable-idle-time-millis: 1800000 keep-alive: true keep-alive-between-time-millis: 30000 pool-prepared-statements: false filters: stat,wall
关键约束关系
keepAliveBetweenTimeMillis应小于minEvictableIdleTimeMillis,否则保活还没触发,连接可能已经被回收。timeBetweenEvictionRunsMillis不宜太大,否则失效连接回收慢。maxWait不宜过长,否则请求会堆积在线程池里。maxActive必须结合 MySQLmax_connections、实例数量和业务峰值一起评估,不能只看单应用。poolPreparedStatements在 MySQL 场景下通常不建议开启,收益不明显。



