动态数据源 是一种在运行时动态切换数据库连接的技术,常用于支持以下场景
- 读写分离:将写操作指向主库,读操作指向从库
- 多租户模式:不同租户使用不同的数据库
- 分库分表:根据规则动态选择目标库
动态数据源的作用
提高系统性能:
- 通过读写分离,将读操作分散到多个从库,降低主库压力。
支持多租户架构
- 根据租户 ID 动态选择数据库,实现数据隔离。
分库分表支持:
- 根据分片规则,动态选择目标数据库
灵活性:
- 无需固定绑定某个数据源,可以根据业务需求动态切换。
动态数据源的底层原理
动态数据源的实现依赖于 Spring 的 AbstractRoutingDataSource 类。其原理如下:
多数据源配置:
- 在应用中定义多个数据源,并将其注入 AbstractRoutingDataSource。
动态数据源选择:
- AbstractRoutingDataSource 会根据上下文中设置的数据源标识(key)动态决定使用哪个数据源
ThreadLocal 存储数据源标识
- 使用ThreadLocal在当前线程中存储数据源标识,确保每次数据库操作都使用正确的数据源
核心方法
- AbstractRoutingDataSource 的 determineCurrentLookupKey() 方法,会根据上下文返回当前使用的数据源标识
Hikari与Druid
HikariCP和Druid是两种常见的数据库连接池实现,它们在Java应用中用于管理高效的数据库连接,提升性能。
HikariCP
简介
- HikariCP是一个轻量级,高性能的JDBC连接池,被广泛认为是目前最快的Java数据库连接池之一。它注重性能和可靠性,适用于高并发场景。
特点
性能优异
- Hikari以极低的开销和快速的响应著称
- 对性能的优化非常深入,如连接池初始化速度块,查询响应低延迟等
轻量级
- 源代码精简,依赖少
- 适合需要高度优化的小型服务器或者微服务架构
简单适用
- 配置项目少,默认配置已经非常高效
- 易集成到SpringBoot等框架上
高可靠性
- 高效的泄漏检测和故障恢复机制
- 多种内置的监控指标
优点
- 性能极高,特别适合低延迟,高吞吐的环境
- 易用性强,开箱即用
- 活跃维护,广泛使用与社区
缺点
- 自定义功能少,相较于Druid较少的内置的扩展工具
- 偏向轻量化,可能需要更多外部的工具支持监控和调试
HiKariCP核心功能
连接池的管理
- 提供最大/最小连接数的动态管理
- 闲置连接清理机制,减少资源的浪费
快速失败机制
- 启动时立刻检测数据连接是否可用,避免运行期才能发现问题
异步初始化
- 支持线程池异步初始化,提升启动速度
连接池泄漏检测
- 可以设置超时时间,自动检测未归还的连接并警告。
高效的数据结构
- 使用队列 + 锁机制,最大化并发性能
核心参数
- 最大连接数(默认10):连接池中的最大连接数(包括空闲连接)。
- 最小连接数(默认10):最小空闲连接数,当空闲连接不足时,会新建连接。
- 连接超时时间(30s):获取连接的超时时间,超时会抛出异常。
- 最大空闲时间(10ms):空闲连接的最大存活时间,超时则被清理。
- 连接的最大存活时间(30ms):即使空闲也会在超过此时间后重建连接
- 验证连接的超时时间(5s):验证连接的超时时间。
- 连接泄露检测时间(0【禁用】)超过此时间未关闭的连接将记录日志。
Druid
简介
- Druid 是阿里巴巴开源的数据库连接池,同时具备强大的监控、扩展和 SQL 分析功能,特别适合复杂场景的企业级应用。
特点
功能丰富
- 提供SQL监控的功能,可以记录慢查询,SQL执行计划
- 支持数据加密,过滤器链等高级功能
良好的兼容性
- 可以兼容更多的数据库,包括 MySQL、PostgreSQL、Oracle 等
- 内置对多种数据库驱动的优化
灵活的扩展能力
- 内置丰富的扩展功能,如连接过滤器、动态数据源切换等
- 支持 SQL 防火墙、防止 SQL 注入。
监控能力
- 提供WebUI,可以查看连接池的状态,SQL执行计划
优点
- 功能全面,适合高级管理和监控的企业应用
- 社区活跃,在国内有广泛支持和使用
- 易于扩展,适合复杂业务场景。
缺点
- 性能略逊于HikariCP,尤其在高并发的情况下
- 配置复杂度相对较高。
- 更大的内存占比
SpringBoot集成
HikariCP(默认连接池)
Spring Boot 默认集成 HikariCP,无需额外配置:
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=root
Druid(手动集成)
需要引入依赖并手动配置:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>最新版本号</version>
</dependency>
配置 application.yml:
spring:
datasource:
druid:
url: jdbc:mysql://localhost:3306/test
username: root
password: root
initialSize: 5
maxActive: 20
filters: stat,wall
数据库连接池的核心参数
- 最小连接数(Minimum idle Connections):数据库连接池在初始化时会创建的最小空闲连接数,用于应对基础负载。
- 最大连接数(Maximum Pool Size):数据库连接池允许的最大连接数,限制同时与数据库交互的最大连接数量
- 空闲连接最大存活时间(idle Timeout):连接池中的空闲连接在多长时间后会被回收,避免资源浪费
- 最大等待时间(Connection Timeout):当所有连接都被占用时,新请求获取连接的最长等待时间。如果超时,则抛出异常
- 初始化连接数(Inital Connections):数据库连接池初始化时创建的连接数
- 阻塞策略(Blocking Queue Behavior):当连接用尽的时候,数据库连接池会决定如何处理新的请求
数据库连接池的阻塞策略
- 抛出异常(Fail Fast):超过等待时间后直接抛出异常,提示资源不足
- 阻塞等待(Block):请求进入阻塞队列,直到有可用的连接为止
- 丢弃策略(Discard Oldest):丢弃最早的请求(如果丢列支持)
- 创建新连接(Dymanic Growth):动态增加连接数(如果配置允许),可能超出最大连接数
典型应用中的参数设置建议
- 小型应用:最小连接数=1,最大连接数=10,等待时间较长。
- 大型应用:增加最大连接数(如50或100),适当缩短空闲连接时间
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。