SpringBoot + ShardingSphere:MySQL 分库分表实战,轻松支撑千万级用户数据
一、开场白:数据库瓶颈,分库分表能救命?
相信很多后端同学都遇到过数据库性能瓶颈的场景。随着业务快速发展,用户量从几万到几十万,再到几百万、千万级,单库单表的性能瓶颈就成了系统发展的最大阻碍。今天咱们就聊聊,分库分表到底怎么设计、怎么落地,SpringBoot + ShardingSphere这种神器组合又是怎么帮我们搞定千万级用户数据的!
二、分库分表:给数据库做"减法",让系统飞起来
2.1 什么是分库分表?
简单说,分库分表就是把一张大表拆成多张小表,甚至分到不同的数据库里。就像一个大仓库,原来所有货物都堆在一个地方,找东西要翻半天。现在按类别分到多个小仓库,找起来就快多了。
- 分库:把数据分到多个数据库中,比如用户1-100万在数据库A,100-200万在数据库B
- 分表:把一张大表按规则拆成多张小表,比如订单表按月份拆成order_01、order_02...
2.2 分库分表的"坑"你踩过吗?
分库分表虽然能解决性能问题,但也会带来新的挑战:
跨库事务,麻烦! 一旦数据分散到多个库,原本简单的事务操作就变复杂了。比如用户下单需要扣库存、生成订单、扣余额,这三个操作可能在不同库,怎么保证一致性?
跨表查询,头大! 想查所有用户的订单?结果订单被分在了10张表里,只能每张表都查一遍再合并,SQL写起来又臭又长。
主键ID怎么生成? 自增ID不行了,容易重复。得用分布式ID(如雪花算法)保证全局唯一。
运维复杂度飙升 表多、库多,备份、迁移、扩容都麻烦。
三、ShardingSphere登场:让分库分表像用单库一样简单!
ShardingSphere是啥?一句话:让分库分表像用单库一样简单!
它是一个开源的分布式数据库中间件,支持分库分表、读写分离、分布式事务等一堆高级功能。有了它,开发同学不用关心底层数据分布细节,就像操作单库一样写代码。
3.1 ShardingSphere的工作原理
ShardingSphere就像一个智能路由器,它拦截你的SQL,根据配置自动路由到对应的库和表,查询结果自动合并,开发不用关心底层细节。
比如你执行 INSERT INTO orders (user_id, order_id) VALUES (123, 456),ShardingSphere会根据user_id自动判断这条数据应该插入哪个库、哪个表,查询时也会自动路由到正确的分片。
3.2 常见分片策略
- 按范围分片:user_id 0-10000在库1,10001-20000在库2
- 按哈希分片:user_id % 4,按用户ID取模分到4个库
- 按日期分片:按月建表,如order_202301、order_202302
四、SpringBoot + ShardingSphere 实战配置
下面用SpringBoot来演示具体的配置方式。以订单表为例,我们按用户ID进行分库分表:
4.1 添加Maven依赖
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
<version>5.3.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
4.2 application.yml配置
spring:
shardingsphere:
datasource:
names: ds0,ds1
ds0:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://localhost:3306/db0
username: root
password: 123456
ds1:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://localhost:3306/db1
username: root
password: 123456
rules:
sharding:
tables:
t_order:
actual-data-nodes: ds$->{0..1}.t_order_$->{0..1}
table-strategy:
standard:
sharding-column: user_id
sharding-algorithm-name: order_inline
database-strategy:
standard:
sharding-column: user_id
sharding-algorithm-name: database_inline
sharding-algorithms:
database_inline:
type: INLINE
props:
algorithm-expression: ds$->{user_id % 2}
order_inline:
type: INLINE
props:
algorithm-expression: t_order_$->{user_id % 2}
props:
sql-show: true # 显示SQL日志,调试用
4.3 业务代码实现
配置完成后,你的业务代码几乎不用变:
@Service
public class OrderService {
@Autowired
private OrderMapper orderMapper;
public void createOrder(Long userId, Order order) {
order.setUserId(userId);
// 这行代码执行时,ShardingSphere会自动根据userId路由到对应的库和表
orderMapper.insert(order);
}
public List<Order> getUserOrders(Long userId) {
// 查询时,ShardingSphere会自动路由到正确的分片
return orderMapper.selectByUserId(userId);
}
}
五、分片键选择:选错了就是"灾难现场"
分片键选择是分库分表设计的关键,选错了数据分布不均,系统性能反而更差。
5.1 分片键选择原则
高基数原则:选择值域范围大的字段,如user_id、order_id,避免用status、gender这种只有几个值的字段。
业务关联原则:选择查询频繁的字段,避免跨分片查询。按user_id分片,查询用户订单就快;按order_id分片,查询用户订单就需要跨分片。
稳定性原则:选择变化频率低的字段,避免频繁的数据迁移。
5.2 路由策略选择
哈希路由:数据分布均匀,适合等值查询,但不支持范围查询。
范围路由:支持范围查询,但可能造成数据倾斜。
复合分片键:对于复杂查询,可以使用多个字段作为分片键。
六、实战避坑指南
6.1 分布式ID生成
分库分表后,自增ID容易重复,需要使用分布式ID:
@Component
public class DistributedIdGenerator {
private final Snowflake snowflake = IdUtil.getSnowflake(1, 1);
public Long nextId() {
return snowflake.nextId();
}
}
6.2 跨库事务处理
分库分表后,跨库事务变得复杂,可以考虑:
- TCC模式:Try-Confirm-Cancel,适合复杂业务场景
- Seata:开源分布式事务解决方案
- 最终一致性:通过消息队列保证数据最终一致
6.3 查询优化
- 避免跨分片查询:尽量在业务层面设计,避免需要跨分片的复杂查询
- 合理使用索引:分片键字段必须建索引
- 读写分离:配合ShardingSphere的读写分离功能,提升查询性能
七、最佳实践建议
- 分库分表前先评估:别一上来就搞,复杂度会上天。先优化SQL、加缓存、读写分离,实在不行再考虑分库分表。
- 主键ID用分布式ID:别用自增,雪花算法或类似方案保证全局唯一。
- 尽量避免跨库、跨表查询:业务设计要配合,查询条件尽量包含分片键。
- 监控和自动化运维要跟上:表多库多容易出问题,建立完善的监控体系。
- ShardingSphere配置要测试充分:分片规则一旦上线,修改成本很高。
- 数据扩容策略:提前规划扩容方案,避免数据迁移时的业务影响。
八、总结
分库分表不是银弹,但在千万级用户数据场景下,确实能救命。SpringBoot + ShardingSphere让分库分表变得简单易用,但也要注意各种"坑",合理设计分片键、路由策略,充分测试,才能让数据库飞起来!
分库分表的关键在于:业务先行,技术为辅。技术只是工具,合理的业务设计和数据模型才是成功的根本。
关注服务端技术精选,获取更多后端实战干货!
你在分库分表中遇到过哪些坑?欢迎在评论区分享你的故事!
标题:SpringBoot + ShardingSphere:MySQL 分库分表实战,轻松支撑千万级用户数据
作者:jiangyi
地址:http://www.jiangyi.space/articles/2025/12/23/1766493120862.html
- 一、开场白:数据库瓶颈,分库分表能救命?
- 二、分库分表:给数据库做"减法",让系统飞起来
- 2.1 什么是分库分表?
- 2.2 分库分表的"坑"你踩过吗?
- 三、ShardingSphere登场:让分库分表像用单库一样简单!
- 3.1 ShardingSphere的工作原理
- 3.2 常见分片策略
- 四、SpringBoot + ShardingSphere 实战配置
- 4.1 添加Maven依赖
- 4.2 application.yml配置
- 4.3 业务代码实现
- 五、分片键选择:选错了就是"灾难现场"
- 5.1 分片键选择原则
- 5.2 路由策略选择
- 六、实战避坑指南
- 6.1 分布式ID生成
- 6.2 跨库事务处理
- 6.3 查询优化
- 七、最佳实践建议
- 八、总结