共计 2431 个字符,预计需要花费 7 分钟才能阅读完成。
背景痛点:为什么需要分布式数据库
当业务数据量增长到百万级甚至更高时,单机 MySQL 会遇到明显的性能瓶颈:

- 数据量超过 500 万后,即使有索引查询速度也会明显下降
- 高并发写入场景下,磁盘 IO 和 CPU 容易成为瓶颈
- 单表数据过大时,ALTER TABLE 等 DDL 操作可能锁表数小时
- 备份恢复时间长,故障恢复风险窗口大
技术选型:为什么选择 ShardingSphere
常见的分布式数据库方案主要有三种:
- 分布式数据库原生方案(如 TiDB、OceanBase)
- 优点:开箱即用,兼容 MySQL 协议
-
缺点:迁移成本高,生态工具需要适配
-
中间件 + 单机数据库方案(如 MyCAT)
- 优点:不改动现有数据库
-
缺点:功能相对简单,社区活跃度低
-
ShardingSphere 方案
- 完整生态:支持分片、读写分离、加密、影子库等
- 低侵入性:可透明化接入现有系统
- 灵活扩展:支持自定义分片算法
核心实现
分片算法原理
ShardingSphere 支持两种基础分片策略:
-
精确分片:=, IN 等精确匹配条件
// 按用户 ID 取模分片 public class UserIdPreciseSharding implements PreciseShardingAlgorithm<Long> { @Override public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Long> shardingValue) {return "ds" + (shardingValue.getValue() % 2); } } -
范围分片:BETWEEN, >, < 等范围条件
// 按订单日期范围分片 public class OrderDateRangeSharding implements RangeShardingAlgorithm<Date> { @Override public Collection<String> doSharding(Collection<String> availableTargetNames, RangeShardingValue<Date> shardingValue) {// 返回所有可能命中的分片} }
Spring Boot 集成示例
-
添加 Maven 依赖
<dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId> <version>5.3.0</version> </dependency> -
配置 YAML 文件
spring: shardingsphere: datasource: names: ds0,ds1 ds0: type: com.zaxxer.hikari.HikariDataSource driver-class-name: com.mysql.jdbc.Driver jdbc-url: jdbc:mysql://localhost:3306/db0 username: root password: 123456 ds1: # 配置同 ds0... rules: sharding: tables: t_order: actual-data-nodes: ds$->{0..1}.t_order_$->{0..15} database-strategy: standard: sharding-column: user_id precise-algorithm-class-name: com.example.UserIdPreciseSharding table-strategy: standard: sharding-column: order_id precise-algorithm-class-name: com.example.OrderIdPreciseSharding
性能考量
分片键选择黄金法则
- 选择高基数(区分度高)的列:如用户 ID 比性别更适合
- 避免选择频繁更新的列:分片键修改会导致数据迁移
- 业务常用查询条件:WHERE user_id=123 应当能路由到具体分片
分布式事务方案
-
XA 事务(强一致)
spring.shardingsphere.rules.sharding.default-database-strategy.standard.xa-transaction-manager-type: Atomikos -
Seata 柔性事务(最终一致)
spring.shardingsphere.rules.sharding.default-database-strategy.standard.transaction-type: BASE
连接池优化建议
- 每个物理分片配置独立连接池
- HikariCP 推荐配置:
ds0: hikari: maximum-pool-size: 20 minimum-idle: 5 connection-timeout: 30000
避坑指南
分片键三大误区
- 使用自增主键作为分片键:会导致新数据集中写入最后一个分片
- 使用 UUID 作为分片键:无法保证均匀分布且范围查询效率低
- 使用枚举值作为分片键:如性别只有 2 个值,无法有效分片
跨分片查询优化
- 避免无分片条件的全表扫描
- 使用绑定表减少 JOIN 查询复杂度:
spring.shardingsphere.rules.sharding.binding-tables: t_order,t_order_item - 合理使用广播表(如省份字典表)
数据迁移注意事项
-
双写迁移步骤:
-
配置新旧库双写
- 全量数据迁移
- 增量数据追平
- 流量切换验证
-
下线旧库
-
使用 ShardingSphere-Scaling 工具
bin/start.sh --config=conf/config.yaml
思考题
如何设计一个适合订单系统的分片策略?考虑以下因素:
– 订单查询主要按用户维度
– 需要支持按时间范围查询
– 商户需要查看自己所有订单
(提示:可以尝试组合分片策略)
正文完
发表至: 数据库技术
近一天内
