SpringBoot项目里,如何让ShardingSphere 5.x和dynamic-datasource和谐共处?一个配置类搞定
SpringBoot项目中ShardingSphere 5.x与dynamic-datasource的深度整合实践在分布式系统架构中数据源管理一直是开发者面临的核心挑战之一。当我们需要同时处理分库分表和多租户数据隔离时ShardingSphere和dynamic-datasource这两个强大的工具往往会狭路相逢。本文将深入探讨如何让它们在SpringBoot生态中和谐共存不仅解决常见的配置冲突问题还会分享一套经过生产验证的最佳实践方案。1. 理解技术栈的定位与冲突根源ShardingSphere 5.x作为分布式数据库中间件的领军者提供了强大的分库分表能力。而dynamic-datasource则是MyBatis-Plus生态中广受欢迎的多数据源管理组件。当两者在同一项目中相遇时冲突主要来自三个方面Bean加载顺序问题ShardingSphere会在Spring容器启动时自动创建DataSource Bean而dynamic-datasource也需要管理数据源代理机制冲突两者都通过动态代理技术对数据源进行增强导致代理嵌套引发异常事务管理兼容性Spring的事务管理器需要明确知道应该管理哪个层级的DataSource关键冲突表现通常为启动时报BeanCurrentlyInCreationException分片规则不生效动态数据源切换失败事务注解(Transactional)行为异常2. 核心配置方案设计2.1 基础环境准备首先确保项目依赖版本兼容推荐使用以下组合dependencies !-- ShardingSphere -- dependency groupIdorg.apache.shardingsphere/groupId artifactIdshardingsphere-jdbc-core-spring-boot-starter/artifactId version5.3.2/version /dependency !-- dynamic-datasource -- dependency groupIdcom.baomidou/groupId artifactIddynamic-datasource-spring-boot-starter/artifactId version3.6.1/version /dependency !-- 其他必要依赖 -- dependency groupIdcom.alibaba/groupId artifactIddruid-spring-boot-starter/artifactId version1.2.16/version /dependency /dependencies2.2 配置类关键实现创建核心配置类ShardingDataSourceConfig这是解决兼容性问题的核心所在Configuration AutoConfigureBefore({DynamicDataSourceAutoConfiguration.class}) public class ShardingDataSourceConfig { Lazy Autowired private DataSource shardingSphereDataSource; Autowired private DynamicDataSourceProperties properties; Bean public DynamicDataSourceProvider dynamicDataSourceProvider() { return new AbstractDataSourceProvider() { Override public MapString, DataSource loadDataSources() { MapString, DataSource dataSourceMap createDataSourceMap(properties.getDatasource()); // 将ShardingSphere数据源纳入动态数据源管理 dataSourceMap.put(sharding, shardingSphereDataSource); return dataSourceMap; } }; } Primary Bean public DataSource dataSource(DynamicDataSourceProvider provider) { DynamicRoutingDataSource ds new DynamicRoutingDataSource(); ds.setPrimary(properties.getPrimary()); ds.setProvider(provider); ds.setStrategy(properties.getStrategy()); return ds; } }关键注解解析注解作用必要性Lazy延迟加载ShardingSphere数据源必须解决循环依赖Primary标记主数据源必须确保事务管理器使用正确数据源AutoConfigureBefore控制配置加载顺序建议确保动态数据源优先初始化3. 多场景下的配置策略3.1 混合使用场景配置在application.yml中配置示例spring: datasource: dynamic: primary: master # 默认数据源 datasource: master: type: com.alibaba.druid.pool.DruidDataSource url: jdbc:mysql://localhost:3306/master username: root password: root slave: type: com.alibaba.druid.pool.DruidDataSource url: jdbc:mysql://localhost:3306/slave username: root password: root shardingsphere: datasource: names: ds0,ds1 ds0: url: jdbc:mysql://localhost:3306/ds0 username: root password: root ds1: url: jdbc:mysql://localhost:3306/ds1 username: root password: root rules: sharding: tables: t_order: actual-data-nodes: ds$-{0..1}.t_order_$-{0..1} table-strategy: standard: sharding-column: order_id precise-algorithm-class-name: com.example.OrderShardingAlgorithm3.2 动态切换与分片协同工作在实际业务代码中可以这样使用Service public class OrderService { // 使用分片数据源 DS(sharding) public void createShardingOrder(Order order) { // 会自动路由到正确的分片 orderMapper.insert(order); } // 使用普通数据源 DS(master) public void createNormalOrder(Order order) { orderMapper.insert(order); } // 事务方法示例 Transactional DS(slave) public void updateOrder(Long id) { // 跨数据源操作需要特别注意事务边界 } }4. 生产环境中的注意事项4.1 性能调优建议连接池配置为不同类型的数据源设置不同的连接池参数spring: datasource: dynamic: datasource: master: # 连接池配置 initial-size: 5 max-active: 20 min-idle: 5 sharding: # ShardingSphere连接池单独配置 initial-size: 10 max-active: 50监控集成建议为每个数据源配置监控Bean public ServletRegistrationBeanStatViewServlet druidServlet() { ServletRegistrationBeanStatViewServlet reg new ServletRegistrationBean(); reg.setServlet(new StatViewServlet()); reg.addUrlMappings(/druid/*); return reg; }4.2 常见问题排查指南问题1启动时报BeanCurrentlyInCreationException检查是否遗漏Lazy注解确认配置类加载顺序问题2分片规则不生效检查数据源是否正确地加入了动态数据源管理确认DS注解没有覆盖分片逻辑问题3事务不生效确保Primary注解配置正确检查事务管理器是否绑定了正确的数据源Bean ConditionalOnMissingBean public PlatformTransactionManager transactionManager(DynamicRoutingDataSource dataSource) { return new DataSourceTransactionManager(dataSource); }在实际项目落地过程中我们发现最大的挑战不在于技术实现本身而在于对两种组件工作原理的深入理解。通过合理的设计不仅能让ShardingSphere和dynamic-datasource和谐共处还能发挥出112的效果——既保留了ShardingSphere强大的分片能力又能利用dynamic-datasource灵活的切换机制。