Spring Boot配合Druid和MyBatis Plus,聊聊Sharding JDBC分表那些事儿
- 问答
- 2026-01-11 00:01:46
- 2
Spring Boot配合Druid和MyBatis Plus,聊聊Sharding JDBC分表那些事儿 综合自开源项目官方文档、技术社区博客及个人实践总结)
好的,咱们直接开聊,当你的项目用Spring Boot搭起来,数据源交给了靠谱的Druid来管理,数据库操作用MyBatis Plus简化了一大半之后,随着数据量咔咔往上涨,单张表慢慢就变得臃肿不堪,查询速度跟蜗牛似的,这时候,分表就成了一个不得不考虑的选择,而Sharding-JDBC,就是帮我们搞定分表这事儿的一把利器,它不是代理,而是个嵌在你应用里的jar包,直接对JDBC层进行了增强,可以理解为一种“智能”的数据源。
为啥要分表?Sharding-JDBC是干啥的?
想象一下,你有一张用户订单表t_order,几年下来积攒了几个亿的数据,你查个最近订单还好,要是想查某个用户一年前的订单,数据库可能就得“吭哧吭哧”全表扫描,效率极低,分表的核心思想就是“化整为零”,把这一张巨大的表,按照某种规则(比如订单创建年份月份、用户ID取模等)拆分成很多张结构完全相同的小表,比如t_order_202401、t_order_202402……t_order_202412,甚至更细。
那应用代码怎么知道要查哪张表呢?总不能写一堆if-else来判断吧?这就是Sharding-JDBC出场的时候了,它的工作就是充当一个“SQL翻译官”和“路由向导”,你的代码还像往常一样,写的SQL是针对逻辑表t_order的,Sharding-JDBC会拦截这条SQL,根据你配置的分表规则,悄悄地把它“翻译”成具体要操作哪张(或哪几张)物理表的SQL,然后执行,最后再把结果合并起来返回给你,操作的好像还是一张表,但实际上数据已经分散存储了,这种对代码侵入性极低的方式,是它最大的优点之一。

怎么把它们攒到一起用?
在Spring Boot项目里整合这三者,步骤很清晰,通过Maven或Gradle把Sharding-JDBC、Druid、MyBatis Plus的依赖都引进来,这里要注意Sharding-JDBC-Spring-Boot-Starter的版本兼容性。
关键的配置都在application.yml文件里,这里有个小技巧,Sharding-JDBC自己可以管理数据源,所以我们通常会把Druid作为Sharding-JDBC底层的“实际”数据源,配置的大致结构是这样的:

- 定义真实数据源: 先配置一个或多个真实的数据源,比如叫
ds0,指定它的连接池类型是com.alibaba.druid.pool.DruidDataSource,并填上URL、用户名、密码等,哪怕你只有一个数据库,Sharding-JDBC也要求你这么配。 - 配置分表规则: 这是核心,在
shardingsphere.rules下面配置。- 指定逻辑表和实际表的关系: 告诉Sharding-JDBC,逻辑表
t_order实际对应哪些物理表,比如t_order_202401, t_order_202402, ... t_order_202412,这里可以用Groovy表达式来简化配置,比如t_order_$->{2024..2024}0$->{1..9}和t_order_$->{2024..2024}$->{10..12}来拼出12张表的名字(注:此处表达式仅为示例,实际需根据ShardingSphere版本支持的语法调整)。 - 指定分片键和分片算法: 这是“路由”的依据,我们选择
order_id(订单ID)作为分片键,然后配置一个分片算法,行表达式分片算法”,直接在里面写一个Groovy表达式,意思是“用订单ID对数据库表的总数(12)取模,得到的余数就是表的后缀”,这样,Sharding-JDBC就能根据每条数据order_id的值,精确地算出它应该落在哪张物理表里,除了取模,还可以根据时间范围、自定义复杂算法等来分片。
- 指定逻辑表和实际表的关系: 告诉Sharding-JDBC,逻辑表
分表后,MyBatis Plus还能愉快使用吗?
基本没问题!MyBatis Plus的那些通用CRUD方法,比如save, getById, updateById, page等,生成的SQL都是针对你定义的实体类对应的“逻辑表”的,这些SQL会被Sharding-JDBC成功拦截并路由到正确的物理表,所以单表的增删改查基本是透明的,无需修改。
有一些坑需要特别注意:
- 分布式主键问题: 如果还依赖数据库自增主键,分表环境下肯定会冲突,所以必须用分布式ID生成器,比如雪花算法,MyBatis Plus内置支持配置雪花算法,在实体类主键字段上加上
@TableId(type = IdType.ASSIGN_ID)即可,这样MP会在插入前自动生成一个Long类型的全局唯一ID,这正是Sharding-JDBC分片所需要的。 - 复杂查询的挑战: 涉及到跨多个分片的查询,比如没有带分片键
order_id的条件,而是根据user_id来查询这个用户的所有订单,Sharding-JDBC会采取“广播”策略,也就是向所有分片都发一次查询,然后把结果聚合起来,虽然功能能实现,但性能会有损耗,甚至可能拖垮数据库。分表后,查询尽量带上分片键,这是最重要的设计原则。 - 事务管理: 由于数据分散在不同分片,原本的本地事务会升级为分布式事务,Sharding-JDBC支持XA等分布式事务,但会有性能开销,在业务设计上,尽量保证单个事务内的操作落在同一个分片内,是避免复杂分布式事务问题的有效手段。
总结一下
用Spring Boot + Druid + MyBatis Plus + Sharding-JDBC来实现分表,是一个很实用的技术组合,Druid管好数据源连接,MyBatis Plus简化单表操作,Sharding-JDBC则无声无息地帮你解决了数据分片的难题,上手不难,配置是重点,但更要紧的是在业务设计阶段就想清楚怎么分片(用什么做分片键)、怎么避免跨分片的复杂操作,把这套体系跑通了,应对千万级甚至亿级数据量的单表压力,心里就有底了。
本文由黎家于2026-01-11发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:http://waw.haoid.cn/wenda/78362.html