Article

分库分表 ShardingSphere

更新于:2026-07-15

第一章:ShardingSphere 概述与核心概念

1.1 什么是 ShardingSphere

概念名称说明注意事项
ShardingSphereApache 基金会旗下的开源分布式数据库中间件套件,提供数据分片、读写分离、数据加密、影子库等能力需区分其三种形态:Sharding-JDBC(客户端)、Sharding-Proxy(代理层)、Sharding-Sidecar(K8s)
定位分布式数据库中间件,增强 JDBC/DataSource/Proxy 层能力不是数据库,而是对现有数据库的增强,兼容 MySQL、PostgreSQL 等协议
核心目标提供透明化、可插拔、可扩展的数据库增强能力支持无侵入或低侵入接入,支持灵活配置与扩展
开源协议Apache 2.0可用于商业项目,具备良好的社区支持

1.2 ShardingSphere 的三大组件:Sharding-JDBC、Sharding-Proxy、Sharding-Sidecar

组件名称说明特点注意事项
Sharding-JDBC轻量级 Java 框架,以 JAR 包形式嵌入应用,直接操作数据库无需额外部署,性能高,适用于 Java 应用仅支持 Java,应用需管理多个数据源,升级依赖需重启应用
Sharding-Proxy数据库代理服务,独立部署,应用通过标准数据库协议连接语言无关,支持多语言客户端,集中管理分片规则需额外部署和维护,存在网络跳转,性能略低于 Sharding-JDBC
Sharding-Sidecar基于 Kubernetes 的数据库代理组件,以 Sidecar 模式运行与云原生架构集成,服务网格模式下自动注入目前社区活跃度较低,生产使用较少,主要用于未来云原生场景探索

1.3 分库分表的基本概念:数据分片、分片键、分片策略、分片算法

概念名称说明注意事项
数据分片将单一数据库或表的数据按规则分散到多个数据库或表中目的是解决单库单表性能瓶颈和存储容量限制
分片键决定数据分布的字段(如 user_id、order_id)应选择高基数、查询频繁的字段,避免热点数据
分片策略定义如何根据分片键进行数据路由的规则,包含分库策略和分表策略支持精确匹配、范围、复合条件等场景
分片算法实现分片策略的具体逻辑,可自定义或使用内置算法算法需保证一致性、可扩展性,避免扩容时大规模数据迁移
逻辑表应用中使用的表名,如 t_order,实际对应多个真实表SQL 编写仍使用逻辑表名,由 ShardingSphere 解析并路由
真实表物理数据库中的实际表,如 t_order_0, t_order_1由分片算法决定插入或查询哪个真实表
数据节点数据源 + 逻辑表 + 真实表的组合,如 ds0.t_order_0每个数据节点对应一个物理存储位置

1.4 读写分离与主从架构支持

概念名称说明注意事项
读写分离将写操作路由到主库,读操作路由到从库,提升读性能适用于读多写少场景,需保证主从同步延迟可控
主从架构一个主库(Master)负责写入,多个从库(Slave)通过 binlog 同步数据需数据库层面支持主从复制机制
负载均衡策略支持轮询、随机等方式在多个从库间分配读请求可根据从库负载动态调整,避免单个从库压力过大
强制主库读通过 Hint 或配置,强制某些读操作走主库用于强一致性要求的查询,避免主从延迟导致数据不一致
中间件角色ShardingSphere 自动识别 SQL 类型并路由不需应用层判断 SQL 类型,实现透明读写分离

1.5 数据加密、影子库、分布式治理等高级特性概览

特性名称说明注意事项
数据加密对敏感字段(如身份证、手机号)进行透明加解密支持 AES、MD5 等算法,逻辑列明文,密文列存储加密数据
影子库为压测流量提供隔离环境,不影响生产数据通过 SQL Hint 或标签识别影子 SQL,路由到影子库执行
分布式治理支持配置中心(ZooKeeper、Nacos)和注册中心管理分片规则实现配置动态刷新、服务发现、熔断降级等
SQL 审计记录 SQL 执行情况,用于安全审计和性能分析可结合日志系统实现审计追踪
链路追踪集成 SkyWalking、Zipkin 等,追踪 SQL 执行链路便于定位慢查询和性能瓶颈
分布式事务支持与 Seata 等框架集成,实现跨库事务一致性建议在必要场景使用,避免滥用影响性能

第二章:Sharding-JDBC 入门实践

2.1 引入 Sharding-JDBC 依赖(Maven 配置)

依赖名称语法用途代码示例注意事项
sharding-jdbc-core<dependency><groupId>org.apache.shardingsphere</groupId><artifactId>sharding-jdbc-core</artifactId><version>4.1.1</version></dependency>核心模块,提供分片、读写分离等功能用于 Java API 或 Spring 非 Boot 项目版本号需根据项目需求选择,推荐 4.x 或 5.x 稳定版
sharding-jdbc-spring-boot-starter<dependency><groupId>org.apache.shardingsphere</groupId><artifactId>sharding-jdbc-spring-boot-starter</artifactId><version>4.1.1</version></dependency>Spring Boot 自动装配支持用于 Spring Boot 项目,简化配置引入后可通过 application.yml 配置分片规则
mysql-connector-java<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.28</version></dependency>MySQL 驱动必须引入,ShardingSphere 通过 JDBC 连接数据库建议使用 8.x 版本,注意时区、SSL 等连接参数
druid-spring-boot-starter<dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.8</version></dependency>数据库连接池可选,用于监控 SQL 执行、连接池状态ShardingSphere 默认使用 HikariCP,也可替换为 Druid

2.2 基于 Java API 的简单分片配置

方法名称语法用途代码示例注意事项
new ShardingRuleConfiguration()ShardingRuleConfiguration config = new ShardingRuleConfiguration();创建分片规则配置对象用于编程方式定义分片规则是 Java API 配置的入口对象
setDataSourceMapconfig.setDataSourceMap(dataSourceMap);设置数据源映射Map<String, DataSource> dataSourceMap = new HashMap<>();需提前创建多个 DataSource 实例
getTableRuleConfigs().add()config.getTableRuleConfigs().add(tableRuleConfig);添加逻辑表的分片规则每个逻辑表对应一个 TableRuleConfiguration必须设置逻辑表名、真实数据节点、分库分表策略
setTableShardingStrategyConfigtableRuleConfig.setTableShardingStrategyConfig(strategyConfig);设置分表策略使用 StandardShardingStrategyConfiguration 等支持标准、复合、Hint 等策略
setDatabaseShardingStrategyConfigtableRuleConfig.setDatabaseShardingStrategyConfig(strategyConfig);设置分库策略同上可与分表策略独立配置
ShardingDataSourceDataSource dataSource = new ShardingDataSource(config);创建 Sharding 数据源应用使用该 DataSource 执行 SQL生成后可注入 Spring 容器或直接使用

2.3 基于 YAML 配置文件的分片规则定义

配置项名称语法用途代码示例注意事项
dataSourcesdataSources: ds0: ..., ds1: ...定义多个数据源每个数据源包含 url、username、password 等数据源名称用于后续规则引用
shardingRuleshardingRule: ...分片规则根配置包含 tables、bindingTables、broadcastTables 等必须配置逻辑表与真实节点映射
tables.[逻辑表名].actualDataNodesactualDataNodes: ds$->{0..1}.t_order_$->{0..1}定义逻辑表对应的真实数据节点使用行表达式生成 ds0.t_order_0, ds0.t_order_1 等行表达式需保证生成合法表名
tables.[逻辑表名].tableStrategytableStrategy: inline: ...配置分表策略支持 inline、standard、complex、hint 等inline 适用于简单表达式,standard 支持自定义类
tables.[逻辑表名].databaseStrategydatabaseStrategy: inline: ...配置分库策略同上可与分表策略组合使用
defaultDataSourceNamedefaultDataSourceName: ds0设置默认数据源未匹配分片规则的 SQL 路由到默认数据源建议设置,避免路由失败

2.4 使用 Spring Boot 集成 Sharding-JDBC

配置项名称语法用途代码示例注意事项
spring.shardingsphere.datasource.namesspring.shardingsphere.datasource.names=ds0,ds1声明所有数据源名称名称用于后续配置引用必须先声明才能使用
spring.shardingsphere.datasource.[ds].typespring.shardingsphere.datasource.ds0.type=com.zaxxer.hikari.HikariDataSource配置数据源类型支持 HikariCP、Druid 等需确保依赖已引入
spring.shardingsphere.sharding.tables.[table].actual-data-nodesspring.shardingsphere.sharding.tables.t_order.actual-data-nodes=ds$->{0..1}.t_order_$->{0..1}配置逻辑表真实节点使用 SpEL 表达式注意转义 $ 和 {}
spring.shardingsphere.sharding.tables.[table].table-strategy.inlinespring.shardingsphere.sharding.tables.t_order.table-strategy.inline.sharding-column=order_id配置行表达式分表策略设置分片列和表达式表达式如 t_order_$->{order_id % 2}
spring.shardingsphere.sharding.tables.[table].database-strategy.inlinespring.shardingsphere.sharding.tables.t_order.database-strategy.inline.sharding-column=user_id配置行表达式分库策略同上可与分表策略组合使用
@SpringBootApplication + @MapperScan@SpringBootApplication @MapperScan("com.example.mapper")启动类注解整合 MyBatis 时需扫描 Mapper 接口ShardingSphere 自动代理 DataSource

2.5 简单 CRUD 操作验证分片效果

操作类型SQL 示例预期行为验证方法注意事项
INSERTINSERT INTO t_order (user_id, order_id, info) VALUES (1, 1001, 'test')根据 user_id 分库,order_id 分表,插入对应真实表查看目标库表是否生成数据分片键必须提供,否则使用默认数据源
SELECTSELECT * FROM t_order WHERE user_id = 1 AND order_id = 1001精确路由到单个真实表使用 EXPLAIN 或日志查看执行计划包含分片键可路由优化,否则需遍历所有表
UPDATEUPDATE t_order SET info = 'new' WHERE user_id = 1 AND order_id = 1001路由到对应真实表执行更新验证目标表数据是否更新不支持跨分片批量更新
DELETEDELETE FROM t_order WHERE user_id = 1 AND order_id = 1001删除指定分片数据验证目标表数据是否删除条件不含分片键将广播到所有表
SELECT(全表)SELECT * FROM t_order全路由(广播)到所有真实表,结果归并查看是否从所有分片查询并合并结果性能较差,生产慎用

第三章:数据分片核心机制

3.1 分片键(Sharding Key)的选择与作用

概念名称说明注意事项
分片键决定数据在分库分表中分布的字段,如 user_id、order_id 等必须出现在 SQL 的 WHERE 条件中才能实现精确路由
作用实现数据水平拆分,决定 SQL 路由到哪个数据库或表是分片策略和算法的输入依据
选择原则高基数、分布均匀、查询频繁、避免热点避免使用时间字段作为唯一分片键,易产生热点
单分片键仅使用一个字段作为分片依据最常见场景,如按 user_id 分库
复合分片键使用多个字段联合决定分片,如 (user_id, order_id)用于复杂路由场景,需使用 ComplexShardingAlgorithm
逻辑表与分片键每个逻辑表可独立定义分片键不同表可使用不同分片键
路由影响包含分片键 → 精确路由;不包含 → 全路由(广播)全路由性能差,应尽量避免

3.2 分片策略(Sharding Strategy)详解

分片策略类型说明对应算法接口注意事项
StandardShardingStrategy标准分片策略,支持单分片键的精确匹配和范围查询StandardShardingAlgorithm最常用,适用于 =、IN、BETWEEN 等操作
ComplexShardingStrategy复合分片策略,支持多分片键联合判断ComplexShardingAlgorithm用于复杂条件组合,性能开销较大
InlineShardingStrategy行表达式分片策略,通过 Groovy 表达式定义分片逻辑无(内置)适用于简单取模、字符串拼接等场景,配置简洁
HintShardingStrategy强制分片策略,通过 Hint 信息(如 ThreadLocal)指定分片值HintShardingAlgorithm绕过 SQL 解析,强制路由到指定库表,用于特殊场景
NoneShardingStrategy不分片策略,所有数据路由到默认数据源用于广播表或默认表

3.3 分片算法(Sharding Algorithm)类型与自定义实现

算法类型说明实现方式注意事项
自定义算法实现 ShardingAlgorithm 接口或其子接口编写 Java 类实现 doSharding 方法需注册到 Spring 容器或配置中
内置算法ShardingSphere 提供的默认实现,如行表达式、取模等通过配置直接使用无需编码,适合简单场景
可插拔架构算法通过 SPI 机制加载,支持动态替换实现接口 + META-INF/services 注册便于扩展和测试
算法配置方式支持在 YAML、Java API、Spring Boot 中配置使用 type 指定算法类型,props 传参自定义算法需指定全类名
算法隔离不同逻辑表可使用不同算法配置独立避免相互影响

3.4 行表达式分片算法(Inline Sharding Algorithm)

方法/配置项名称语法用途代码示例注意事项
行表达式语法ds_$->{user_id % 2}t_order_$->{order_id % 4}定义数据源或表名生成规则ds0.t_order_0, ds1.t_order_1 等使用 Groovy 语法,支持算术运算、字符串拼接
sharding-columnsharding-column: user_id指定分片列必须与表达式中变量一致仅支持单列
algorithm-expressionalgorithm-expression: ds_$->{user_id % 2}设置行表达式用于分库或分表策略表达式结果必须对应真实数据节点
支持操作符+, -, *, /, %, {}, []构建复杂表达式t_order_$->{order_id % 4 / 2}避免除零、越界等异常
性能高效,无需反射调用适用于简单规则不适合复杂逻辑

3.5 标准分片算法(Standard Sharding Algorithm)

方法名称语法用途代码示例注意事项
doShardingCollection<String> doSharding(Collection<String> availableTargetNames, PreciseShardingValue<T> shardingValue)精确分片(=, IN)根据 value 返回目标表名必须返回非空集合,否则路由失败
doSharding (Range)Collection<String> doSharding(Collection<String> availableTargetNames, RangeShardingValue<T> shardingValue)范围分片(BETWEEN)遍历 availableTargetNames 判断是否匹配性能较差,建议避免大范围查询
PreciseShardingValueshardingValue.getValue()获取精确值(如 = 1001)Long userId = shardingValue.getValue();用于精确匹配
RangeShardingValueshardingValue.getValueRange().hasLowerBound()获取范围值(如 BETWEEN 1 AND 10)判断上下界并匹配需遍历所有节点
自定义类实现public class MyStandardAlgorithm implements StandardShardingAlgorithm<Long>实现标准分片逻辑需实现两个 doSharding 方法必须有无参构造函数

3.6 复合分片算法(Complex Sharding Algorithm)

方法名称语法用途代码示例注意事项
doShardingCollection<String> doSharding(Collection<String> availableTargetNames, Collection<ShardingValue> shardingValues)处理多个分片键遍历 shardingValues 获取 user_id 和 order_idshardingValues 包含所有分片键条件
ShardingValueif (value instanceof ListShardingValue) { ... }判断值类型(List、Range)支持 IN、BETWEEN 等多种条件需处理不同类型
多键联合判断if (userId % 2 == 0 && orderId % 4 < 2) return Arrays.asList("t_order_0");实现复杂路由逻辑可结合业务规则性能开销大,慎用
配置方式type: COMPLEX, props: algorithm-class-name: com.example.MyComplexAlgYAML 或 Spring Boot 配置必须指定 algorithm-class-name不支持行表达式

3.7 Hint 强制分片算法

方法名称语法用途代码示例注意事项
HintManager.getInstance()HintManager hintManager = HintManager.getInstance();获取 Hint 管理器实例必须在线程内使用基于 ThreadLocal 实现
addDatabaseShardingValuehintManager.addDatabaseShardingValue("t_order", "user_id", 1);强制指定分库值路由到 user_id=1 对应的库优先级高于 SQL 解析
addTableShardingValuehintManager.addTableShardingValue("t_order", "order_id", 1001);强制指定分表值路由到 order_id=1001 对应的表可单独使用
setMasterRouteOnlyhintManager.setMasterRouteOnly();强制读操作走主库用于强一致性查询与读写分离配合使用
closehintManager.close();释放资源,必须调用建议使用 try-with-resources否则可能导致内存泄漏

第四章:分片策略与算法配置方式

4.1 基于 Spring Boot + YAML 的分片配置详解

配置项名称语法用途代码示例注意事项
spring.shardingsphere.sharding.tables.t_order.actual-data-nodesds$->{0..1}.t_order_$->{0..1}定义真实数据节点使用行表达式生成 4 个节点节点必须真实存在
spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.sharding-columnorder_id设置分表列必须与表达式匹配
spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.algorithm-expressiont_order_$->{order_id % 2}设置分表表达式支持 Groovy 语法注意转义 $
spring.shardingsphere.sharding.tables.t_order.database-strategy.inline.sharding-columnuser_id设置分库列同上
spring.shardingsphere.sharding.tables.t_order.database-strategy.inline.algorithm-expressionds$->{user_id % 2}设置分库表达式同上
spring.shardingsphere.sharding.default-data-source-nameds0设置默认数据源未匹配规则的 SQL 路由至此建议设置

4.2 基于 Java API 的分片规则编程式配置

方法名称语法用途代码示例注意事项
new TableRuleConfigurationTableRuleConfiguration orderRule = new TableRuleConfiguration("t_order", "ds$->{0..1}.t_order_$->{0..1}");创建逻辑表规则设置逻辑表名和真实节点节点表达式需正确
new InlineShardingStrategyConfigurationnew InlineShardingStrategyConfiguration("user_id", "ds$->{user_id % 2}")创建行表达式分库策略用于 databaseStrategy第一个参数为分片列,第二个为表达式
new StandardShardingStrategyConfigurationnew StandardShardingStrategyConfiguration("order_id", "com.example.OrderIdShardingAlgorithm")创建标准分片策略需提前定义算法类用于复杂逻辑
new ShardingRuleConfigurationShardingRuleConfiguration config = new ShardingRuleConfiguration();创建分片规则总配置添加所有 tableRule 和策略最终用于构建 DataSource
new ShardingDataSourceDataSource dataSource = new ShardingDataSource(config);构建 Sharding 数据源应用使用此数据源执行 SQL可注入 Spring 容器

4.3 使用 Spring 命名空间配置(XML 方式,了解即可)

配置元素名称语法用途代码示例注意事项
sharding:data-source<sharding:data-source id="shardingDataSource" ... />定义 Sharding 数据源需引入 shardingsphere-namespace 命名空间仅适用于传统 Spring 项目
sharding:inline-strategy<sharding:inline-strategy sharding-column="user_id" algorithm-expression="ds$->{user_id % 2}" />配置行表达式策略用于 database-strategy 或 table-strategy已逐渐被 YAML 和注解取代
sharding:standard-strategy<sharding:standard-strategy sharding-column="order_id" precise-algorithm-class-name="com.example.PreciseAlg" />配置标准分片策略需实现 PreciseShardingAlgorithm 接口支持精确和范围算法
sharding:key-generator<sharding:key-generator type="SNOWFLAKE" column="order_id" />配置分布式主键生成器用于生成全局唯一 ID

4.4 分片配置参数说明与最佳实践

配置参数名称说明最佳实践
actual-data-nodes真实数据节点表达式使用行表达式生成,确保覆盖所有物理表
sharding-column分片列名称选择高基数、查询频繁的字段
algorithm-expression行表达式内容避免复杂计算,保证性能
strategy 配置分库分表策略尽量使用标准或行表达式策略,避免全路由
default-data-source-name默认数据源必须设置,防止路由失败
binding-tables绑定表配置将关联表(如 t_order 和 t_order_item)配置为绑定表,避免笛卡尔积
broadcast-tables广播表配置将小表(如字典表)配置为广播表,写操作同步到所有库
sql.show是否打印 SQL开发环境开启,生产环境关闭

第五章:读写分离机制

5.1 读写分离原理与应用场景

概念说明注意事项
原理将数据库的写操作(INSERT, UPDATE, DELETE)路由到主库(Master),读操作(SELECT)路由到从库(Slave),通过主从复制同步数据基于 MySQL 的 binlog 复制机制实现数据一致性
核心组件MasterDataSource(主库)、SlaveDataSource(从库)、LoadBalanceStrategy(负载均衡策略)ShardingSphere 通过解析 SQL 判断读写类型
应用场景高并发读多写少的业务场景,如电商商品查询、社交平台动态展示等不适用于强一致性要求极高的场景
优势提升读性能、减轻主库压力、提高系统吞吐量需注意主从延迟(Replication Delay)问题
限制事务中的读操作默认走主库,保证一致性非事务 SELECT 才可能走从库

5.2 配置主从数据源

配置项YAML 示例说明
spring.shardingsphere.datasource.namesnames: master,slave0,slave1定义所有数据源名称
spring.shardingsphere.datasource.master.typetype: com.zaxxer.hikari.HikariDataSource主库数据源类型
spring.shardingsphere.datasource.master.driver-class-namedriver-class-name: com.mysql.cj.jdbc.Driver数据库驱动类
spring.shardingsphere.datasource.master.jdbc-urljdbc-url: jdbc:mysql://localhost:3306/ds_master主库连接地址
spring.shardingsphere.datasource.slave0.jdbc-urljdbc-url: jdbc:mysql://localhost:3306/ds_slave0从库连接地址
spring.shardingsphere.rules.readwrite-splitting.data-sources.<ds_name>readwrite-splitting:
data-sources:
ms-ds:
write-data-source-name: master
read-data-source-names:
- slave0
- slave1
定义主从逻辑关系,ms-ds 为逻辑数据源名

5.3 读写分离负载均衡策略

策略类型配置值说明使用场景
轮询策略ROUND_ROBIN请求按顺序轮流分配到各个从库请求分布均匀,适合从库性能相近
随机策略RANDOM随机选择一个从库简单高效,但可能分布不均
权重策略自定义实现按预设权重分配流量从库配置不同时使用(如 2:1)
配置方式load-balancer-name: ROUND_ROBIN在 readwrite-splitting 中配置可通过 SPI 扩展自定义策略

最佳实践:生产环境推荐使用 ROUND_ROBIN,简单稳定。

5.4 强制走主库(Hint)机制

方法代码示例说明
HintManager 设置try (HintManager hintManager = HintManager.getInstance()) {
hintManager.setWriteDataSourceOnly();
// 此后的查询都走主库
orderMapper.selectById(1001);
}
使用 try-with-resources 确保资源释放
setWriteDataSourceOnly()hintManager.setWriteDataSourceOnly();强制所有读操作也走主库
适用场景强一致性查询 / 主从延迟敏感业务 / 事务后立即查询避免因主从延迟导致的数据不一致
注意事项必须在同一线程中调用,基于 ThreadLocal 实现不支持跨线程传递

5.5 与分库分表的整合使用

整合方式说明配置要点
分库 + 读写分离每个分片库都配置主从结构每个 ds_${0..n} 都是一个主从逻辑组
分表 + 读写分离分表不影响读写路由读写分离在数据源层,分表在表层
完整架构分库分表 + 读写分离 + 负载均衡构建高可用高性能分布式数据库架构

YAML 配置结构示例:

rules:
  sharding:
    tables: ...
  readwrite-splitting:
    data-sources:
      ds_0:
        write-data-source-name: ds_0_master
        read-data-source-names:
          - ds_0_slave0
          - ds_0_slave1
      ds_1: ...

注意事项

  • 主从配置在 readwrite-splitting
  • 分片规则在 sharding
  • 逻辑表引用的是主从逻辑数据源
  • 避免配置冲突

第六章:分布式主键与 ID 生成

6.1 分布式环境下主键冲突问题

问题说明解决方案
自增主键冲突多库多表环境下,各库自增 ID 可能重复改用分布式唯一 ID 生成器
数据合并困难分片数据迁移或合并时 ID 冲突使用全局唯一 ID
水平扩展限制自增主键无法跨库保证唯一性分布式 ID 支持无限扩展
典型场景插入 t_order 表,order_id 在 ds0.t_order_0 和 ds1.t_order_1 中不能重复使用 Snowflake 或 UUID

6.2 内置分布式主键生成策略

策略类型值说明优点缺点
UUIDUUID生成 32 位字符串(含 -)全局唯一、性能高长度长、无序、影响索引性能
SNOWFLAKESNOWFLAKE64 位 Long 型 ID,含时间戳+机器码+序列号有序、递增、适合索引依赖系统时钟,时钟回拨可能导致问题
LEAFLEAF_SEGMENT美团开源,基于数据库号段预加载高并发、低延迟需额外部署 LEAF 服务
DEFAULTDEFAULT使用数据库自增(仅单库单表)简单不适用于分片环境

推荐使用SNOWFLAKE 适用于大多数场景。

6.3 自定义主键生成器

步骤说明示例代码
实现接口实现 org.apache.shardingsphere.spi.keygen.ShardingKeyGenerator 接口public class CustomKeyGenerator implements ShardingKeyGenerator
重写方法generateKey() 方法返回 Comparable 类型@Override
public Comparable<?> generateKey() {
return System.currentTimeMillis() + Thread.currentThread().getId();
}
SPI 注册META-INF/services/org.apache.shardingsphere.spi.keygen.ShardingKeyGenerator 文件中添加实现类全名com.example.CustomKeyGenerator
配置使用在 YAML 或 Java API 中引用type: CUSTOM

6.4 主键生成策略的配置方式

YAML 配置方式:

spring:
  shardingsphere:
    rules:
      sharding:
        tables:
          t_order:
            actual-data-nodes: ds$->{0..1}.t_order_$->{0..1}
            table-strategy:
              standard:
                sharding-column: order_id
                sharding-algorithm-name: t-order-inline
            key-generate-strategy:
              column: order_id
              key-generator-name: snowflake
        key-generators:
          snowflake:
            type: SNOWFLAKE
            props:
              worker-id: 123
          uuid:
            type: UUID

Java API 配置方式:

// 主键生成配置
KeyGenerateStrategyConfiguration keyStrategy = 
    new KeyGenerateStrategyConfiguration("order_id", "SNOWFLAKE");

// 主键生成器配置
Properties props = new Properties();
props.setProperty("worker-id", "123");
ShardingKeyGeneratorConfiguration keyGenConfig = 
    new ShardingKeyGeneratorConfiguration("SNOWFLAKE", props);

// 构建表规则
TableRuleConfiguration orderRule = 
    new TableRuleConfiguration("t_order", "ds$->{0..1}.t_order_$->{0..1}");
orderRule.setKeyGenerateStrategyConfiguration(keyStrategy);
orderRule.setShardingKeyGeneratorConfig(keyGenConfig);

最佳实践

  • 使用 SNOWFLAKE 并设置 worker-id 避免集群冲突
  • 主键列必须配置 key-generate-strategy
  • 生产环境避免使用 UUID 作为索引列

第七章:数据加密机制

7.1 数据加密的必要性与场景

项目说明注意事项
必要性防止敏感数据(如身份证、手机号、银行卡号)在数据库中明文存储,满足合规要求(如 GDPR、等保)即使数据库被拖库,也能保护核心数据
加密层级在 ShardingSphere 中属于逻辑层加密,应用无需感知数据库中存储的是密文,应用使用明文
典型场景用户个人信息加密、支付信息保护、日志脱敏、合规审计要求不建议对所有字段加密,影响性能和索引
透明性对应用透明,SQL 仍使用逻辑列名操作开发者无需修改业务代码
局限性加密列无法使用范围查询(如 ><)、不支持 LIKE 模糊查询(除非使用固定偏移)推荐对等值查询字段加密

7.2 逻辑列与密文列的概念

概念说明示例
逻辑列(Logic Column)应用层使用的列名,SQL 中直接引用SELECT user_name, phone FROM t_user WHERE phone = '13800138000' 中的 phone
密文列(Cipher Column)数据库中实际存储的加密字段t_user 表中 phone_cipher 存储加密后的手机号
辅助列(Assisted Query Column)可选,用于支持模糊查询或哈希查询phone_hash 存储手机号的 MD5 值,用于等值匹配
关系一个逻辑列对应一个或多个物理列(cipher + assisted)逻辑列 phone → 物理列 phone_cipher, phone_hash
配置要求必须明确指定逻辑列、密文列、加密算法ShardingSphere 自动完成加解密转换

7.3 加密算法配置(AES、MD5 等)

算法类型配置 type 值说明是否可逆适用场景
AESAES对称加密,使用密钥加解密✅ 可逆手机号、邮箱、地址等需解密使用的字段
MD5MD5哈希算法,不可逆❌ 不可逆仅用于等值比对,如密码校验(但推荐使用更安全的 BCrypt)
CHARCHAR明文存储(仅脱敏展示)调试或脱敏场景
CHOOSECHOOSE根据配置选择 AES 或 MD5灵活配置
自定义算法自定义类名实现 EncryptAlgorithm 接口按实现满足特殊加密需求

最佳实践

  • 敏感信息使用 AES
  • 密码建议使用 BCrypt(需自定义实现)
  • 避免使用 MD5 存储密码(安全性低)

7.4 加解密配置与使用流程

步骤说明配置示例(YAML)
1. 定义加密规则spring.shardingsphere.rules.encrypt 下配置encrypt:
encryptors:
aes_encryptor:
type: AES
props:
aes-key-value: 123456abcde
2. 配置加密表与列指定哪些表的哪些列需要加密 tables:
t_user:
columns:
phone:
cipher-column: phone_cipher
encryptor-name: aes_encryptor
3. 应用使用逻辑列SQL 中使用 phone 而非 phone_cipherINSERT INTO t_user(phone) VALUES('13800138000')
4. 自动加解密ShardingSphere 拦截 SQL,自动加密写入,解密读取无需代码改动
5. 数据库结构物理表需包含 phone_cipher 字段类型通常为 VARCHAR(255)

7.5 查询与插入时的透明加解密

操作流程示例
INSERT1. SQL 使用逻辑列 phone
2. ShardingSphere 获取明文
3. 使用 AES 加密为密文
4. 写入 phone_cipher 字段
INSERT INTO t_user(phone) VALUES('13800138000') → 实际写入 phone_cipher = ‘abc123xyz’
SELECT1. SQL 查询 phone
2. 从 phone_cipher 读取密文
3. 自动解密为明文
4. 返回给应用
SELECT phone FROM t_user → 返回 ‘13800138000’
WHERE 查询条件中的明文被加密后用于查询密文列WHERE phone = '13800138000'WHERE phone_cipher = '加密后的值'
辅助查询列若配置 assisted-query-column,则使用哈希值进行等值匹配WHERE phone_hash = MD5('13800138000')
限制不支持 ORDER BY phone(密文无序)、不支持 GROUP BY phone建议对加密列仅做等值查询

第八章:影子库(Shadow Database)用于压测

8.1 影子库的概念与作用

概念说明价值
影子库(Shadow Database)与生产库结构相同但用于压测的独立数据库避免压测流量影响真实用户
影子表(Shadow Table)被压测的特定逻辑表(如 t_order)精准控制压测范围
作用在不影响生产环境的前提下,使用真实流量对新架构、SQL 优化、版本升级进行压测验证提升系统稳定性,降低上线风险
核心思想”影子”流量与”真实”流量并行,但写入不同库流量复制,数据隔离

8.2 影子库与生产库的隔离机制

隔离维度说明实现方式
数据源隔离影子库使用独立的数据源,与生产库完全物理隔离配置不同的 JDBC URL、用户名、密码
网络隔离影子库通常部署在独立网络或测试环境防止资源争抢
资源隔离影子库可使用较低配置,不影响生产性能成本可控
数据清理影子库数据可随时清空,不影响生产支持重复压测
权限控制运维人员可控制影子库访问权限安全可控

8.3 影子表与影子规则配置

配置项YAML 示例说明
spring.shardingsphere.rules.shadow.data-sources.<shadow_name>shadow:
data-sources:
shadow_ds:
source-data-source-name: ds_0
shadow-data-source-name: shadow_ds_0
定义影子数据源映射关系
spring.shardingsphere.rules.shadow.tables.t_order tables:
t_order:
data-source-names:
- shadow_ds
指定 t_order 表启用影子规则
spring.shardingsphere.rules.shadow.columncolumn: sharding指定用于判断影子流量的列(如 sharding)
spring.shardingsphere.rules.shadow.operationoperation: INSERT,UPDATE指定哪些操作触发影子路由

8.4 基于 SQL Hint 的影子路由

方法代码示例说明
HintManager 启用影子try (HintManager hintManager = HintManager.getInstance()) {
hintManager.setShadow(true);
orderService.createOrder(order);
}
在代码中强制开启影子路由
自动识别(列匹配)当 SQL 中包含 sharding = 'shadow' 时自动路由无需代码改动,通过 SQL 条件触发
HTTP Header 传递结合网关,在 Header 中传递影子标记全链路压测常用方式
优先级Hint > 列匹配规则Hint 强制生效

8.5 与真实流量并行的压测方案

步骤说明技术要点
1. 流量复制将生产流量复制一份到影子环境使用日志、消息队列或代理工具
2. 标记影子流量在 SQL 或请求中添加影子标记如设置 sharding=‘shadow’ 或使用 Hint
3. 并行执行同一条 SQL 同时在生产库和影子库执行生产库处理真实请求,影子库记录性能
4. 监控对比对比 SQL 执行时间、慢查询、TPS 等指标验证优化效果
5. 安全保障影子库不返回结果给用户,仅用于监控防止数据泄露
优势真实场景压测、零业务侵入、可重复验证适用于 SQL 优化、索引调整、版本升级

最佳实践

  • 影子库与生产库网络隔离
  • 压测期间监控数据库负载
  • 使用独立线程池执行影子 SQL,避免阻塞主流程

第九章:Sharding-Proxy 入门与使用

9.1 Sharding-Proxy 架构与工作原理

概念说明特点
定位分布式数据库中间件,以代理形式提供数据库服务类似 MySQL Proxy,但功能更强大
架构模型客户端 → Sharding-Proxy → 真实数据库(MySQL/PostgreSQL)应用无感知,透明接入
协议兼容支持 MySQL / PostgreSQL 二进制协议可使用标准客户端工具连接
核心功能SQL 解析与路由、分片执行、结果归并、读写分离、数据加密、影子库功能与 ShardingSphere-JDBC 一致
部署方式独立进程部署,可集群化 + 负载均衡适合异构语言环境
对比 JDBC 模式Proxy 模式对应用完全透明,JDBC 模式需引入依赖Proxy 更适合多语言、遗留系统

9.2 安装与启动 Sharding-Proxy

步骤操作命令/说明
1. 下载从 Apache ShardingSphere 官网下载二进制包apache-shardingsphere-5.x.x-sharding-proxy-bin.tar.gz
2. 解压解压到指定目录tar -zxvf apache-shardingsphere-5.x.x-sharding-proxy-bin.tar.gz
3. 目录结构sharding-proxy/
├── bin/
├── conf/
├── lib/
└── logs/
4. 启动使用 start.sh 脚本启动bin/start.sh 3307(指定端口,默认 3307)
5. 验证查看日志 logs/stdout.log 是否启动成功或使用 mysql -h127.0.0.1 -P3307 -uroot -p 连接
6. 停止bin/stop.sh发送 STOP 信号

注意:需提前安装 Java 8+ 环境。

9.3 配置 server.yaml 与 config-sharding.yaml

server.yaml(全局配置):

# 权限配置
authentication:
  users:
    root:
      password: root
    sharding:
      password: sharding
      authorizedSchemas: sharding_db

# 通用属性
props:
  max-connections-size-per-query: 1
  executor-size: 16  # 工作线程数
  proxy-backend-query-fetch-size: 1000
  proxy-front-end-executor-size: 16
  sql-show: true  # 是否打印 SQL

config-sharding.yaml(分片规则):

schemaName: sharding_db

dataSources:
  ds_0:
    url: jdbc:mysql://127.0.0.1:3306/ds_0?serverTimezone=UTC&useSSL=false
    username: root
    password: root
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
  ds_1:
    url: jdbc:mysql://127.0.0.1:3306/ds_1?serverTimezone=UTC&useSSL=false
    username: root
    password: root
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50

rules:
- !SHARDING
  tables:
    t_order:
      actualDataNodes: ds_${0..1}.t_order_${0..1}
      tableStrategy:
        standard:
          shardingColumn: order_id
          shardingAlgorithmName: t_order_inline
      keyGenerateStrategy:
        column: order_id
        keyGeneratorName: snowflake

  shardingAlgorithms:
    t_order_inline:
      type: INLINE
      props:
        algorithm-expression: t_order_${order_id % 2}

  keyGenerators:
    snowflake:
      type: SNOWFLAKE

说明

  • schemaName 对应逻辑数据库名
  • actualDataNodes 定义真实数据节点
  • 支持 config-readwrite-splitting.yaml、config-encrypt.yaml 等独立配置

9.4 使用 MySQL/PostgreSQL 客户端连接 Proxy

客户端连接命令说明
MySQL 命令行mysql -h127.0.0.1 -P3307 -uroot -p默认端口 3307,用户在 server.yaml 中定义
Navicat / DBeaver新建 MySQL 连接,主机 127.0.0.1,端口 3307可视化操作分片表
JDBC 连接jdbc:mysql://127.0.0.1:3307/sharding_db应用可通过 Proxy 访问逻辑库
验证分片执行 INSERT INTO t_order(order_id) VALUES(1), (2);观察数据是否分布到不同表
注意事项确保 Proxy 正在运行、防火墙开放端口、数据库服务可访问连接失败检查日志

9.5 Proxy 模式下的分片与读写分离验证

验证项操作预期结果
分片插入INSERT INTO t_order(order_id, user_id) VALUES(1001, 1), (1002, 2);数据应分布到 ds_0.t_order_1 和 ds_1.t_order_0
分片查询SELECT * FROM t_order WHERE order_id = 1001;返回对应分片数据,SQL 被路由到单一节点
广播查询SELECT * FROM t_order;查询所有分片并合并结果
读写分离配置 readwrite-splitting 规则后,执行 SELECT读请求应走从库(可通过日志或 sql-show 验证)
Hint 强制主库使用 /* sharding hint: write_ds */ 注释读操作也走主库
性能监控查看 logs/stdout.log 中的 SQL 日志确认路由正确性与执行时间

建议:开启 sql-show: true 便于调试。

第十章:Spring Boot 集成与配置详解

10.1 Spring Boot 自动装配机制

组件自动配置类说明
ShardingSphereDataSourceShardingSphereAutoConfiguration根据 application.yml 自动创建数据源
依赖引入shardingsphere-jdbc-core-spring-boot-starter启用自动装配
条件装配基于 @ConditionalOnClass, @ConditionalOnProperty只有配置了规则才生效
配置前缀spring.shardingsphere所有配置项的根路径
启动流程1. 读取 YAML 配置
2. 构建数据源
3. 注册为 Spring Bean
4. 替换默认 DataSource
对 MyBatis/JPA 透明

10.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/ds0?serverTimezone=UTC&useSSL=false
        username: root
        password: root
      ds1:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://localhost:3306/ds1?serverTimezone=UTC&useSSL=false
        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
                sharding-algorithm-name: t-order-inline
            key-generate-strategy:
              column: order_id
              key-generator-name: snowflake
          t_order_item:
            actual-data-nodes: ds${0..1}.t_order_item_${0..1}
            table-strategy:
              standard:
                sharding-column: order_id
                sharding-algorithm-name: t-order-item-inline

        sharding-algorithms:
          t-order-inline:
            type: INLINE
            props:
              algorithm-expression: t_order_${order_id % 2}
          t-order-item-inline:
            type: INLINE
            props:
              algorithm-expression: t_order_item_${order_id % 2}

        key-generators:
          snowflake:
            type: SNOWFLAKE
            props:
              worker-id: 1

      # 读写分离
      readwrite-splitting:
        data-sources:
          ms-ds:
            write-data-source-name: ds0
            read-data-source-names:
              - ds0
              - ds1
            load-balancer-name: round-robin

      # 加密(可选)
      encrypt:
        encryptors:
          aes-encryptor:
            type: AES
            props:
              aes-key-value: 123456abc
        tables:
          t_user:
            columns:
              phone:
                cipher-column: phone_cipher
                encryptor-name: aes-encryptor

    props:
      sql-show: true  # 显示实际执行 SQL

10.3 多数据源配置与事务管理注意事项

项目说明建议
本地事务单一分片操作支持本地事务@Transactional 有效
分布式事务跨分片操作需引入 Seata 或 AtomikosShardingSphere 支持 XA 和 BASE 事务
事务限制广播表更新不保证原子性、读写分离中事务内读走主库避免跨库复杂事务
连接泄漏确保 DataSource 配置合理连接池参数使用 HikariCP 并设置超时
Hint 与事务HintManager 必须在事务开始前设置否则可能路由错误

10.4 与 MyBatis / JPA 的整合使用

MyBatis 整合:

<!-- Maven 依赖 -->
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
    <version>5.3.2</version>
</dependency>
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>3.0.3</version>
</dependency>
@Mapper
public interface OrderMapper {
    @Insert("INSERT INTO t_order (order_id, user_id) VALUES (#{orderId}, #{userId})")
    void insert(Order order);

    @Select("SELECT * FROM t_order WHERE order_id = #{orderId}")
    Order selectById(Long orderId);
}

✅ 无需额外配置,ShardingSphere 自动拦截 MyBatis 的 SQL。

Spring Data JPA 整合:

@Entity
@Table(name = "t_order")
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long orderId;
    private Integer userId;
    // getter/setter
}

@Repository
public interface OrderRepository extends JpaRepository<Order, Long> {
}

⚠️ 注意

  • JPA 的 @GeneratedValue 与 ShardingSphere 冲突,必须关闭(使用 key-generate-strategy)
  • 建议使用 GenerationType.NONE 或自定义 ID 生成

10.5 配置项详解与常见错误排查

问题现象可能原因解决方案
Cannot resolve datasourcedatasource.names 配置错误或数据源未定义检查 names 与实际数据源名称一致
SQL 路由错误分片算法表达式错误检查 algorithm-expression 语法
主键生成失败未配置 key-generate-strategy确保分片列配置了主键生成器
读写分离不生效未开启 readwrite-splitting 或负载均衡配置错误检查规则名称与数据源映射
启动报错 ClassNotFoundException缺少数据库驱动手动添加 mysql-connector-java 依赖
事务跨分片失败未配置分布式事务引入 Seata 或使用 @ShardingSphereTransactionType
sql-show 不打印props.sql-show 未开启设置为 true 并检查日志级别

调试建议

  • 开启 sql-show: true
  • 使用 HintManager 强制路由测试
  • 检查 actual-data-nodes 是否匹配真实表结构

第十一章:高阶特性与扩展机制

11.1 自定义分片算法 SPI 扩展

类型接口说明实现步骤
标准分片StandardShardingAlgorithm支持单分片键的精确/范围查询实现 doSharding() 方法
复合分片ComplexKeysShardingAlgorithm支持多分片键联合路由处理 Collection shardingValues
Hint 分片HintShardingAlgorithm基于 Hint 强制路由,忽略 SQL 中的分片条件适用于分片键不在 SQL 中的场景
行表达式分片InlineShardingAlgorithm内置,支持 t_order_${id % 2} 表达式无需自定义

SPI 扩展步骤:

  1. 实现对应接口:
public class CustomDBShardingAlgorithm implements StandardShardingAlgorithm<Long> {
    @Override
    public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Long> shardingValue) {
        return "ds_" + (shardingValue.getValue() % 2);
    }
}
  1. META-INF/services/org.apache.shardingsphere.sharding.spi.ShardingAlgorithm 文件中添加类全名:
com.example.CustomDBShardingAlgorithm
  1. YAML 配置引用:
sharding-algorithms:
  custom-db-algorithm:
    type: CUSTOM
    props:
      strategy: STANDARD
      algorithm-class-name: com.example.CustomDBShardingAlgorithm

适用场景:复杂业务逻辑分片(如按城市+时间组合分片)。

11.2 分布式事务支持(与 Seata 整合)

事务模式说明配置方式
XA 模式强一致性,基于两阶段提交(2PC)需数据库支持 XA,性能较低
BASE 模式最终一致性,基于 Seata 的 AT 模式高性能,推荐生产使用
本地事务单分片内事务,Spring @Transactional 可用默认模式

整合 Seata 步骤:

  1. 添加依赖:
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>shardingsphere-jdbc-core</artifactId>
    <version>5.3.2</version>
</dependency>
<dependency>
    <groupId>io.seata</groupId>
    <artifactId>seata-spring-boot-starter</artifactId>
    <version>1.7.1</version>
</dependency>
  1. 配置 application.yml:
spring:
  shardingsphere:
    transaction:
      type: BASE  # 或 XA
    props:
      proxy-transaction-type: BASE
  1. 使用 @GlobalTransactional 注解:
@GlobalTransactional
public void transfer(Order order, Item item) {
    orderMapper.insert(order);
    itemMapper.update(item);
}

注意:跨分片更新必须使用分布式事务,否则不保证一致性。

11.3 配置中心与注册中心集成(ZooKeeper, Nacos)

组件作用配置方式
配置中心动态管理分片、读写分离等规则支持 ZooKeeper、Nacos、Etcd
注册中心服务发现与高可用Proxy 集群注册
优势配置热更新、集群协同、降级容错无需重启应用

Nacos 配置示例:

spring:
  shardingsphere:
    mode:
      type: Cluster
      repository:
        type: Nacos
        props:
          server-lists: 127.0.0.1:8848
          namespace: shardingsphere
          data-id: sharding-config
          group: DEFAULT_GROUP

ZooKeeper 配置示例:

mode:
  type: Cluster
  repository:
    type: ZooKeeper
    props:
      retryIntervalMilliseconds: 500
      timeToLiveSeconds: 60
      maxRetries: 3
      operationTimeoutMilliseconds: 500
      server-lists: localhost:2181
      namespace: sharding-sphere

最佳实践:生产环境推荐使用 Nacos,界面友好,集成简单。

11.4 SQL 解析引擎与执行优化

组件说明优化点
SQL Parser基于 ANTLR 解析 SQL,生成 AST支持 MySQL/PostgreSQL/Oracle/SQLServer
Routing Engine根据分片键路由到目标数据节点减少广播查询
Rewrite Engine改写 SQL 以适应分片结构如 t_order → t_order_1
Merge Engine归并来自多个数据节点的结果集支持排序、分页、聚合
执行优化并行执行、连接池优化、批处理提升吞吐量

优化建议:

  • 避免 SELECT *,明确字段提升解析效率
  • 使用绑定表(Binding Table)减少归并压力
  • 合理设置 max-connections-size-per-query

11.5 链路追踪与监控指标暴露

监控方式说明集成方案
链路追踪跟踪 SQL 从入口到执行的完整路径支持 SkyWalking、Zipkin、OpenTelemetry
Metrics 暴露暴露 JVM、连接池、SQL 执行等指标集成 Prometheus + Grafana
日志增强记录 SQL、路由、耗时等信息sql-show: true + 自定义 Appender

Prometheus 配置:

props:
  metrics:
    type: PROMETHEUS
    host: 127.0.0.1
    port: 9199
    node-path: /metrics

访问 http://127.0.0.1:9199/metrics 可获取指标:

# HELP sharding_sphere_execution_sql_count Total SQL execution count
# TYPE sharding_sphere_execution_sql_count counter
sharding_sphere_execution_sql_count{type="SELECT"} 123

运维价值:实现 APM 全景监控,快速定位性能瓶颈。

第十二章:性能调优与运维实践

12.1 分片策略对查询性能的影响

策略查询性能适用场景建议
取模分片均匀分布,但范围查询需扫描所有分片写多读少,数据均匀
范围分片范围查询快,但易产生热点时间序列数据(如日志)配合分片键预估数据量
哈希分片分布较均匀,支持等值查询用户 ID、订单号等
复合分片灵活,但路由复杂多维度查询避免过度设计

⚠️ 避免:order_id 递增 + 取模,可能导致热点(集中在最新分片)。

12.2 全局表、广播表的使用场景

表类型说明使用场景注意事项
广播表每个分片库都有一份完整副本字典表、配置表、权限规则写操作会广播到所有节点,影响性能
全局表同步所有节点,通常用于维度表与分片表关联查询(JOIN)需保证数据一致性

配置方式:

tables:
  t_config:
    actual-data-nodes: ds0.t_config,ds1.t_config
    table-strategy:
      none:

优势:避免跨库 JOIN,提升查询效率。

12.3 分页查询优化与归并排序

问题说明优化方案
深层分页LIMIT 1000000, 10 需从各分片拉取大量数据改用 WHERE id > ? LIMIT 10(基于索引)
归并排序多分片结果需在内存归并确保 ORDER BY 字段为分片键或全局唯一
内存占用归并大量数据可能导致 OOM设置 max-merge-group-count 限制

优化建议:

  • 分页尽量基于分片键(如 user_id)
  • 避免 SELECT * + ORDER BY non-sharding-column
  • 使用游标分页(Cursor-based Pagination)

12.4 慢 SQL 分析与执行计划查看

工具方法说明
ShardingSphere 日志开启 sql-show: true查看实际执行的 SQL 和路由信息
数据库 EXPLAIN在目标分片库执行 EXPLAIN分析单个分片的执行计划
慢查询日志开启 MySQL 慢日志定位耗时 SQL
APM 工具SkyWalking / Prometheus监控 SQL 执行时间分布

分析流程:

  1. 通过日志定位慢 SQL
  2. 确认路由到哪些分片
  3. 在对应分片库执行 EXPLAIN
  4. 优化索引或分片策略

12.5 运维命令与健康检查

功能命令/方式说明
健康检查/actuator/health(Spring Boot)返回 shardingsphere 状态
元数据查看SHOW TABLES; / DESC t_order;(通过 Proxy)查看逻辑表结构
运行时配置通过配置中心动态更新规则无需重启
连接池监控SHOW DATABASE CONNECTIONS;(Proxy)查看当前连接数
数据一致性检查自定义脚本比对分片数据定期校验
优雅下线关闭写入 → 等待读完成 → 停止服务避免数据丢失

运维建议

  • 建立监控告警体系
  • 定期演练故障恢复
  • 使用蓝绿部署或灰度发布更新分片规则

第十三章:常见问题与最佳实践

13.1 跨分片查询的限制与解决方案

限制类型说明解决方案
JOIN 查询不支持跨分片 JOIN(非绑定表)✅ 绑定表(Binding Table):相同分片键的表配置为绑定关系,可高效 JOIN
✅ 应用层归并:在代码中分步查询后合并
✅ 冗余字段:将关联字段冗余到主表(如订单表冗余用户姓名)
子查询复杂子查询可能无法正确路由✅ 拆分为多个简单查询
✅ 避免在 WHERE 子句中使用非分片键的子查询
聚合函数SUM, COUNT, AVG 需从所有分片拉取数据✅ 使用归并引擎自动处理
⚠️ 注意内存占用,避免全表聚合
排序(ORDER BY)非分片键排序需在内存归并✅ 尽量按分片键排序
✅ 分页使用 WHERE id > ? LIMIT n 替代 LIMIT offset, n
分页(Paging)深层分页性能差(如 LIMIT 1000000, 10)✅ 游标分页(Cursor-based Pagination):基于有序 ID 分页
✅ 二次查询法:先查 ID 再查详情
DISTINCT / GROUP BY非分片键去重或分组需归并✅ 尽量在分片键上操作
✅ 应用层处理复杂去重逻辑

最佳实践

  • 设计表结构时优先考虑分片键一致性
  • 复杂查询建议在应用层或中间层处理
  • 使用 sql-show: true 验证实际执行路径

13.2 分布式事务的取舍与建议

事务模式一致性性能适用场景建议
本地事务单分片内强一致单一数据节点操作默认使用
XA(2PC)强一致低(锁资源久)对一致性要求极高,可接受性能损失不推荐生产大规模使用
BASE(Seata AT)最终一致大多数跨分片业务场景✅ 生产推荐
TCC / Saga最终一致复杂业务流程,需自定义补偿适合订单、支付等长流程

决策建议:

  • 优先避免跨分片事务:通过合理分片设计让相关数据落在同一分片
  • 能用本地事务就不用分布式事务
  • 强一致场景:评估业务容忍度,必要时使用 XA
  • 高并发场景:使用 BASE 模式 + 重试机制
  • 幂等性保障:所有写操作必须实现幂等,防止重试导致数据错乱

⚠️ 注意:ShardingSphere 的分布式事务依赖外部协调器(如 Seata Server),需额外部署和维护。

13.3 分片键设计的最佳实践

原则说明示例
高基数(High Cardinality)分片键取值范围大,避免热点✅ 用户 ID、订单 ID
❌ 性别、状态(低基数)
均匀分布(Uniform Distribution)数据在各分片间分布均衡✅ user_id % 4
❌ 时间戳取模(易热点)
频繁查询(Query Frequency)分片键应是 WHERE 条件中最常出现的字段✅ 订单查询按 user_id 分片
❌ 按 order_date 分片但常查用户订单
避免热点(Hotspot Avoidance)防止单一分片负载过高✅ 使用 Snowflake ID + 取模
❌ 自增 ID 导致写入集中在最新分片
不变性(Immutability)分片键一旦确定不应修改✅ 用户 ID
❌ 用户所属区域(可能变更)
组合分片键多维度查询时使用复合分片✅ (user_id, order_type) 联合分片

设计流程:

  1. 分析核心业务查询模式
  2. 识别高频查询字段
  3. 评估数据量和增长趋势
  4. 选择合适的分片算法(取模、哈希、范围等)
  5. 压测验证分布均匀性

推荐分片键

  • 用户中心:user_id
  • 订单系统:order_id(Snowflake)或 user_id
  • 日志系统:DATE + HOUR 范围分片

13.4 数据迁移与扩容方案

阶段操作工具/方法
1. 预评估评估数据量、迁移时间、停机窗口mysqldump, pt-online-schema-change
2. 双写准备新旧结构并存,开启双写应用代码改造,同时写入新旧库
3. 数据迁移将旧数据同步到新分片结构✅ ShardingSphere-Scaling(官方工具)
✅ DataX / Canal + 自定义脚本
4. 数据比对校验新旧数据一致性自定义比对脚本(按分片比对)
5. 流量切换逐步将读写流量切到新结构灰度发布、路由规则调整
6. 回滚预案准备回退方案备份旧数据,监控异常

扩容示例(2 → 4 分片):

  • 原规则:ds_${user_id % 2}, t_order_${user_id % 2}
  • 新规则:ds_${user_id % 4}, t_order_${user_id % 4}
  • 使用 一致性哈希 可减少数据迁移量

最佳实践

  • 使用 ShardingSphere-Scaling 实现在线迁移
  • 迁移期间开启影子库验证新结构性能
  • 避免在业务高峰期操作

13.5 版本升级与兼容性注意事项

项目注意事项建议
版本策略ShardingSphere 采用语义化版本(MAJOR.MINOR.PATCH)优先升级 PATCH 版本
配置兼容性YAML 配置格式可能变化(如 4.x → 5.x 变化大)仔细阅读升级指南
SPI 接口变更自定义算法可能因接口变动失效升级前检查 SPI 接口是否兼容
SQL 兼容性新版本可能增强 SQL 解析,旧 SQL 行为可能变化先在测试环境验证
依赖冲突新版本可能升级底层依赖(如 Netty, HikariCP)检查 dependency:tree 避免冲突
Proxy 协议兼容Proxy 对客户端协议兼容性较好但仍需测试连接和查询

升级流程:

  1. 备份配置与数据
  2. 在测试环境验证新版本
  3. 检查 Breaking Changes
  4. 更新依赖并测试 SPI 扩展
  5. 灰度发布到生产
  6. 监控运行状态

推荐策略

  • 生产环境使用稳定版本(Stable Release)
  • 避免直接跨大版本升级(如 4.x → 5.x)
  • 关注官方公告和社区反馈

⚠️ 重要提示:升级前务必阅读官方发布的 Migration Guide。