拓冰建站拓冰建站
首页 / 资讯中心 / 正文

SpringBoot多数据源配置,一文讲透

在真实业务中多数据源几乎是绕不开的需求读写分离、分库分表、对接多个业务库、租户隔离……很多开发者第一次遇到时第一反应是“配两个DataSource不就行了”结果一上事务就报错一换数据源就失效。今天我把SpringBoot多数据源配置一次讲透。一、为什么需要多数据源典型场景有三个读写分离主库写、从库读缓解数据库压力多业务库订单库和用户库物理隔离互不影响多租户每个租户独立数据库保证数据安全。这些场景的共同点是同一个应用需要访问多个数据库且需要动态切换。二、核心方案AbstractRoutingDataSourceSpring早为我们准备了抽象类AbstractRoutingDataSource。它的原理很简单内部维护一个MapObject, DataSource运行时通过determineCurrentLookupKey()返回的key从Map中选出对应的数据源。我们只需要继承它并用ThreadLocal保存当前线程要用的数据源标识。java复制下载public class DynamicDataSource extends AbstractRoutingDataSource { Override protected Object determineCurrentLookupKey() { return DataSourceContextHolder.getDataSource(); } }DataSourceContextHolder用ThreadLocal存key保证线程安全请求结束后记得remove防止内存泄漏。三、配置步骤1. 定义多个数据源在application.yml中配置主库和从库的连接信息然后用ConfigurationProperties分别绑定到两个DataSourceBean。java复制下载Bean(master) ConfigurationProperties(spring.datasource.master) public DataSource masterDataSource() { return DataSourceBuilder.create().build(); } Bean(slave) ConfigurationProperties(spring.datasource.slave) public DataSource slaveDataSource() { return DataSourceBuilder.create().build(); }2. 注册动态数据源创建DynamicDataSource把master和slave放入Map并设置默认数据源。java复制下载Bean public DataSource dynamicDataSource(Qualifier(master) DataSource master, Qualifier(slave) DataSource slave) { MapObject, Object map new HashMap(); map.put(master, master); map.put(slave, slave); DynamicDataSource ds new DynamicDataSource(); ds.setTargetDataSources(map); ds.setDefaultTargetDataSource(master); return ds; }3. 用AOP自动切换自定义注解DataSource(slave)通过AOP在方法执行前设置key执行后清除。java复制下载Around(annotation(dataSource)) public Object around(ProceedingJoinPoint pjp, DataSource dataSource) throws Throwable { DataSourceContextHolder.setDataSource(dataSource.value()); try { return pjp.proceed(); } finally { DataSourceContextHolder.clear(); } }在Service方法上标注DataSource(slave)查询自动走从库。四、事务与常见坑坑一事务中切换数据源失效。Spring事务在方法开始时绑定连接若在事务内切换数据源实际仍用原连接。解决方案把切换注解放在事务方法外层或使用Transactional(propagation REQUIRES_NEW)开启新事务。坑二多数据源事务不一致。默认的DataSourceTransactionManager只能管理一个数据源。跨库事务需要JTA或Seata等分布式事务框架复杂度陡增。如果业务允许尽量用最终一致性替代强一致。坑三MyBatis-Plus多数据源。如果用了MyBatis-Plus可直接引入dynamic-datasource-spring-boot-starter用DS(slave)注解比手动实现更省事。但原理仍是AbstractRoutingDataSource。坑四连接池配置。每个数据源都要独立配HikariCP参数否则默认池大小可能拖垮数据库。监控各池的活跃连接数及时调整。五、总结多数据源配置的核心是AbstractRoutingDataSource ThreadLocal AOP。理解了这个模型无论读写分离还是多租户都能灵活应对。但要记住多数据源不是越多越好每增加一个数据源事务、连接池、监控的复杂度都成倍上升。能用单库解决的别急着拆。真需要拆时先把事务边界想清楚再动手写代码。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门