当前位置: 首页 > news >正文

ShardingSphere系列04:MybatisPlus动态数据源与ShardingJdbc分表策略的深度整合实践

1. 为什么需要整合动态数据源与分表策略

在实际业务开发中,我们经常会遇到两个典型场景:一是需要根据业务模块访问不同的数据库(多数据源),二是单个数据表数据量过大需要分表存储(分库分表)。MybatisPlus的动态数据源和ShardingJdbc分别擅长解决这两个问题,但将它们整合在一起使用时却会遇到不少坑。

我最近在一个电商项目中就遇到了这样的需求:订单数据需要按用户ID分表存储,同时又要能灵活切换到日志库、商品库等其他数据源。刚开始尝试时,发现直接用MybatisPlus的@DS注解切换数据源会导致ShardingJdbc的分表规则失效,反之亦然。经过多次调试才找到正确的整合方式。

这种整合的核心价值在于:

  • 业务代码无需关心底层是单表还是分表
  • 可以透明地使用@DS注解切换不同业务数据源
  • 分表策略对上层完全透明,就像操作单表一样简单

2. 环境准备与依赖配置

2.1 基础环境搭建

首先确保你的Spring Boot项目版本在2.3.x以上,我这里用的是2.7.12版本。数据库准备两个实例:

  • 主库:table_sharding(用于订单分表)
  • 从库:product_db(模拟商品数据)

创建订单表结构(分4个表):

CREATE TABLE `order_info_0` ( `id` bigint NOT NULL, `user_id` bigint NOT NULL, `product_id` bigint DEFAULT NULL, `amount` decimal(10,2) DEFAULT NULL, `create_time` datetime DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

记得同时创建order_info_1到order_info_3共4个相同结构的表。

2.2 关键依赖管理

pom.xml中需要特别注意这些依赖的版本兼容性:

<!-- MybatisPlus核心 --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.3.1</version> </dependency> <!-- 动态数据源 --> <dependency> <groupId>com.baomidou</groupId> <artifactId>dynamic-datasource-spring-boot-starter</artifactId> <version>3.6.1</version> </dependency> <!-- ShardingSphere --> <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId> <version>5.3.2</version> </dependency> <!-- 数据源驱动 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.2.16</version> </dependency>

特别提醒:ShardingSphere 5.x版本与MybatisPlus 3.5+存在一些SPI加载冲突,需要额外添加以下配置类:

@Configuration public class ShardingConfig { @PostConstruct void init() { System.setProperty("org.apache.shardingsphere.sql.parser.sql.cache.enabled", "false"); } }

3. 核心配置实战

3.1 动态数据源桥接配置

这是整个整合最关键的环节,我们需要创建一个DataSourceConfiguration来桥接两者:

@Configuration @AutoConfigureBefore({DynamicDataSourceAutoConfiguration.class}) public class DataSourceConfig { private static final String SHARDING_DS_NAME = "sharding"; @Autowired private DynamicDataSourceProperties properties; @Lazy @Resource private DataSource shardingDataSource; @Bean public DynamicDataSourceProvider dynamicDataSourceProvider() { return new AbstractDataSourceProvider() { @Override public Map<String, DataSource> loadDataSources() { Map<String, DataSource> dataSourceMap = createDataSourceMap(properties.getDatasource()); // 将ShardingSphere管理的数据源纳入动态数据源体系 dataSourceMap.put(SHARDING_DS_NAME, shardingDataSource); return dataSourceMap; } }; } @Primary @Bean public DataSource dataSource() { DynamicRoutingDataSource ds = new DynamicRoutingDataSource(); ds.setPrimary(properties.getPrimary()); ds.setProvider(dynamicDataSourceProvider()); return ds; } }

这个配置类做了三件重要的事情:

  1. 加载MybatisPlus动态数据源的常规配置
  2. 获取ShardingSphere创建的分片数据源
  3. 将分片数据源注册为动态数据源的一个特殊数据源

3.2 YAML配置详解

application.yml需要分层配置:

spring: shardingsphere: datasource: names: sharding sharding: type: com.alibaba.druid.pool.DruidDataSource url: jdbc:mysql://localhost:3306/table_sharding username: root password: 123456 rules: sharding: tables: order_info: actual-data-nodes: sharding.order_info_$->{0..3} table-strategy: standard: sharding-column: user_id precise-algorithm-class-name: com.example.config.OrderShardingAlgorithm key-generators: snowflake: type: SNOWFLAKE datasource: dynamic: primary: master datasource: master: url: jdbc:mysql://localhost:3306/product_db username: root password: 123456 log: url: jdbc:mysql://192.168.1.100:3306/log_db username: log_user password: log@123

注意几个关键点:

  1. ShardingSphere的数据源名称必须与桥接配置中的SHARDING_DS_NAME一致
  2. 动态数据源的primary设置会影响@DS注解的默认行为
  3. 分片算法建议使用自定义类实现更灵活的分片逻辑

4. 业务层实现技巧

4.1 实体与Mapper设计

对于分表实体,需要特别注意两点:

@Data @TableName("order_info") // 逻辑表名 public class OrderInfo { @TableId(type = IdType.ASSIGN_ID) private Long id; private Long userId; // 分片键 private Long productId; private BigDecimal amount; private Date createTime; }

Mapper接口保持常规写法即可:

@Mapper public interface OrderMapper extends BaseMapper<OrderInfo> { @DS("sharding") List<OrderInfo> selectByUser(@Param("userId") Long userId); }

4.2 服务层的最佳实践

在Service层使用时,推荐这种写法:

@Service public class OrderServiceImpl extends ServiceImpl<OrderMapper, OrderInfo> { // 分表操作统一使用sharding数据源 @DS("sharding") public void processOrder(OrderInfo order) { save(order); // 会自动根据userId分片 // 切换到商品库查询 Product product = productService.getById(order.getProductId()); } // 多数据源混合操作 public void fullProcess(OrderInfo order) { // 默认使用master数据源 logService.record(order); // 切换到分片数据源 processOrder(order); } }

4.3 自定义分片算法示例

对于复杂分片逻辑,建议实现标准分片算法:

public class OrderShardingAlgorithm implements StandardShardingAlgorithm<Long> { @Override public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Long> shardingValue) { // 按userId的哈希值取模分片 int size = availableTargetNames.size(); long mod = shardingValue.getValue() % size; return "order_info_" + Math.abs(mod); } }

5. 常见问题排查指南

5.1 典型错误与解决方案

问题一:分表规则不生效现象:数据总是插入到第一个物理表 排查步骤:

  1. 检查sharding-column是否与实体字段一致
  2. 确认分片算法返回的表名后缀在actual-data-nodes范围内
  3. 在yaml中添加sql-show: true查看实际路由

问题二:动态切换失效现象:@DS注解切换后仍使用默认数据源 解决方案:

  1. 检查DataSourceConfiguration是否加了@Primary
  2. 确认没有在多个地方重复创建DataSource bean
  3. 在启动日志中搜索"DynamicDataSource"确认初始化顺序

5.3 性能优化建议

  1. 分片键选择:尽量选择离散度高的字段,避免热点问题
  2. 连接池配置:建议为分片数据源设置更大的maxPoolSize
  3. 批量操作:使用ShardingSphere提供的批量插入API提升性能
  4. 分布式事务:对于跨分片操作,考虑使用Seata集成

我在实际项目中还发现一个有用的技巧:对于需要频繁跨库查询的场景,可以创建一个视图数据库,通过ETL工具定期同步需要关联查询的数据,这样既能保持分片的优势,又能解决关联查询的性能问题。

http://www.jsqmd.com/news/696481/

相关文章:

  • Keras深度学习框架入门与实践指南
  • 告别盲猜!用ESP8266+INA226给你的DIY电源做个精准“体检”(附完整代码)
  • 定时器外部时钟
  • AMD Ryzen 处理器终极调校指南:RyzenAdj 完整教程
  • 支持多协议转换的工业物联网智能网关应用
  • 从零到一:掌握Trace32 PRACTICE脚本(cmm)的自动化调试核心技巧
  • 柜子定制哪家强?2026年实力厂家推荐揭晓,橱柜定制/榻榻米定制/万华翡凡全屋定制/衣柜定制,柜子定制公司哪家好 - 品牌推荐师
  • TCP-快速重传与超时重传的困惑解析
  • 基于SRT算法的单精度浮点除法器
  • nli-MiniLM2-L6-H768部署案例:为RAG系统注入句子级逻辑校验能力
  • 各区县路网密度数据(2013-2023年)
  • Xinference-v1.17.1效果实测:在Ubuntu上轻松运行多模态AI模型
  • AI试衣系统源码-一键换衣换装-支持姿态识别+纹理融合-批量生成-SAAS模式-电商创业利器
  • 2026年无尘车间闸机优质厂家推荐指南:上海小区闸机、上海工业园区闸机、上海工地实名制闸机、上海智能静电闸机、上海电子厂静电闸机选择指南 - 优质品牌商家
  • 自然语言处理趋势分析
  • 商超装修吊楣装饰铝拉网
  • Qwen3-4B-Instruct惊艳效果:科研基金申请书创新点凝练与润色
  • 从零构建可审计合约系统,深度解析ISO 26262 ASIL-D级嵌入式项目中Contract Interface设计规范
  • BigQuery ML UI增强功能解析与实战指南
  • UHMWPE板源头厂家哪家好
  • iPaaS系统集成运维避坑指南:接口失控、数据错乱高频故障成因解析与全流程解决方案
  • 面向医疗 Agent 的 Harness 符合 HIPAA 的日志脱敏
  • Flux2-Klein-9B-True-V2快速部署:torch28环境+CUDA 12.8一键适配指南
  • 2026年专业的庐阳装修/毛坯房装修/家庭装修榜单优选公司 - 行业平台推荐
  • 第三篇:Unity进阶阶段(商业项目能力)
  • AI查看文档001
  • 2026年Q2西南水晶标优质服务商排行榜:四川PVC工作牌公司、四川PVC工作证公司、四川UV水晶标公司、四川工作牌公司选择指南 - 优质品牌商家
  • 杀戮尖塔2 MOD与修改器介绍
  • 遇到新问题怎么办?AI 的“抄作业“大法
  • 弄懂这56个Python使用技巧(轻松掌握Python高效开发)