Mysql学习笔记:ShardingSphere-JDBC分库分表+读写分离嵌入式实战指南
一、ShardingSphere-JDBC 是什么
ShardingSphere-JDBC 是 ShardingSphere 的嵌入式模式——JDBC 驱动直接嵌入应用内,应用通过它连接数据库,它负责把 SQL 路由到正确的物理库/表。
| 特性 | JDBC(嵌入应用) | Proxy(独立服务) |
|---|---|---|
| 部署方式 | 引入 Maven 依赖 | 部署独立 Docker 容器 |
| 网络开销 | 无中间跳转 | 多一次网络转发 |
| 管理成本 | 随应用部署 | 独立运维 |
| 适用场景 | 单体应用、微服务 | 多应用共享、异构语言 |
本文场景:上一篇我们用 Proxy 搭建了 2 集群 × 1主2从的 MySQL 分片架构,现在用 Spring Boot 应用通过 JDBC 模式直连同一个 MySQL 集群。
如果你还没部署后端 MySQL 集群,请先阅读上一篇 ShardingSphere-Proxy 搭建指南 的 五~六节,先把 6 个 MySQL 跑起来。
二、架构说明
Spring Boot 应用
│
▼
ShardingSphere-JDBC(嵌入应用内)
│
│ user_id % 2 → 分库
│ order_id % 2 → 分表
│ 写→Master,读→Slave
│
├── ds_0 (user_id 偶数)
│ ├── 22220 Master(写入)
│ ├── 22221 Slave1(读取)
│ └── 22222 Slave2(读取)
│
└── ds_1 (user_id 奇数)
├── 22223 Master(写入)
├── 22224 Slave1(读取)
└── 22225 Slave2(读取)
分片规则:
user_id % 2 == 0→ Cluster A(ds_0)user_id % 2 == 1→ Cluster B(ds_1)order_id % 2 == 0→t_order_0order_id % 2 == 1→t_order_1
读写分离:
INSERT / UPDATE / DELETE→ MasterSELECT→ Slave(轮询负载均衡)
三、环境准备
| 工具 | 版本 |
|---|---|
| Java | 17+ |
| Spring Boot | 4.0.7 |
| ShardingSphere-JDBC | 5.5.2 |
| MyBatis Plus | 3.5.16(spring-boot4-starter) |
| MySQL | 8.0(6个容器,已在运行) |
四、项目搭建
4.1 项目结构
sharding-jdbc-demo/
├── pom.xml
└── src/main/
├── java/com/example/sharding/
│ ├── ShardingJdbcApplication.java
│ ├── entity/Order.java
│ ├── mapper/OrderMapper.java
│ └── service/OrderService.java
└── resources/
├── application.yml
└── sharding-config.yaml
4.2 依赖配置
关键 Maven 依赖(pom.xml):
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>4.0.7</version>
</parent>
<properties>
<java.version>17</java.version>
<shardingsphere.version>5.5.2</shardingsphere.version>
</properties>
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MyBatis Plus(Spring Boot 4.x 专用) -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot4-starter</artifactId>
<version>3.5.16</version>
</dependency>
<!-- ShardingSphere-JDBC(5.5.x ✅ 原生支持 snakeyaml 2.x) -->
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc</artifactId>
<version>${shardingsphere.version}</version>
</dependency>
<!-- MySQL JDBC 驱动 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
⚠️ 版本注意:
- MyBatis Plus
mybatis-plus-spring-boot3-starter只支持 Spring Boot 3.x,Spring Boot 4.x 必须使用mybatis-plus-spring-boot4-starter,版本 ≥ 3.5.13- ShardingSphere-JDBC 5.5.x 原生支持
snakeyaml 2.x(Spring Boot 3+ 内置),无需额外兼容
4.3 配置数据源与分片规则
application.yml — 使用 ShardingSphere 驱动方式:
spring:
datasource:
# 使用 ShardingSphere 提供的 JDBC 驱动
driver-class-name: org.apache.shardingsphere.driver.ShardingSphereDriver
# 指定分片配置文件位置(classpath 根目录)
url: jdbc:shardingsphere:classpath:sharding-config.yaml
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
map-underscore-to-camel-case: true
sharding-config.yaml — 核心分片 + 读写分离配置:
dataSources:
# ===== Cluster A (ds_0) =====
ds_0_master:
dataSourceClassName: com.zaxxer.hikari.HikariDataSource
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:22220/sharding_db?useSSL=false&allowPublicKeyRetrieval=true
username: root
password: root123
ds_0_slave1:
dataSourceClassName: com.zaxxer.hikari.HikariDataSource
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:22221/sharding_db?useSSL=false&allowPublicKeyRetrieval=true
username: root
password: root123
ds_0_slave2:
dataSourceClassName: com.zaxxer.hikari.HikariDataSource
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:22222/sharding_db?useSSL=false&allowPublicKeyRetrieval=true
username: root
password: root123
# ===== Cluster B (ds_1) =====
ds_1_master:
dataSourceClassName: com.zaxxer.hikari.HikariDataSource
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:22223/sharding_db?useSSL=false&allowPublicKeyRetrieval=true
username: root
password: root123
ds_1_slave1:
dataSourceClassName: com.zaxxer.hikari.HikariDataSource
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:22224/sharding_db?useSSL=false&allowPublicKeyRetrieval=true
username: root
password: root123
ds_1_slave2:
dataSourceClassName: com.zaxxer.hikari.HikariDataSource
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:22225/sharding_db?useSSL=false&allowPublicKeyRetrieval=true
username: root
password: root123
rules:
# ===== 分片规则 =====
- !SHARDING
tables:
t_order:
actualDataNodes: ds_$->{0..1}.t_order_$->{0..1}
databaseStrategy:
standard:
shardingColumn: user_id
shardingAlgorithmName: db_inline
tableStrategy:
standard:
shardingColumn: order_id
shardingAlgorithmName: table_inline
shardingAlgorithms:
db_inline:
type: INLINE # Groovy 表达式路由
props:
algorithm-expression: ds_${user_id % 2} # 偶数→ds_0,奇数→ds_1
table_inline:
type: INLINE
props:
algorithm-expression: t_order_${order_id % 2}
# ===== 读写分离 =====
- !READWRITE_SPLITTING
dataSourceGroups:
ds_0:
writeDataSourceName: ds_0_master
readDataSourceNames:
- ds_0_slave1
- ds_0_slave2
ds_1:
writeDataSourceName: ds_1_master
readDataSourceNames:
- ds_1_slave1
- ds_1_slave2
props:
sql-show: true # 控制台打印实际路由 SQL
🔑 关键说明:
- JDBC 配置中的
ds_0_master等名称,与!READWRITE_SPLITTING中的writeDataSourceName/readDataSourceNames对应!SHARDING中的actualDataNodes: ds_$->{0..1}.t_order_$->{0..1}使用 Groovy 表达式语法,$->{}表示范围- 这里用的是读写分离与分片共存:ShardingSphere 先分片决定目标组(ds_0/ds_1),再走读写分离决定是 Master 还是 Slave
五、功能验证
Java 实体类、Mapper、Service 与普通 MyBatis Plus 用法完全一致,唯一区别是数据源配置改为 ShardingSphereDriver,此处不再赘述。
直接用 MySQL 客户端插入数据验证分片效果:
INSERT INTO t_order (order_id, user_id, product_name, status) VALUES
(1, 1, '商品A', 1),
(2, 2, '商品B', 1),
(3, 3, '商品C', 1),
(4, 4, '商品D', 1);
SELECT * FROM t_order ORDER BY order_id;
应用启动后,控制台输出实际 SQL 路由日志:
# 插入:全部走 Master
INSERT INTO t_order (order_id,user_id,product_name,status) VALUES (?,?,?,?)
→ ds_1_master ::: INSERT INTO t_order_1 VALUES (1, 1, 商品A, 1) # user_id=1 奇数 → ds_1, order_id=1 奇数 → t_order_1
→ ds_0_master ::: INSERT INTO t_order_0 VALUES (2, 2, 商品B, 1) # user_id=2 偶数 → ds_0, order_id=2 偶数 → t_order_0
→ ds_1_master ::: INSERT INTO t_order_1 VALUES (3, 3, 商品C, 1) # user_id=3 奇数 → ds_1, order_id=3 奇数 → t_order_1
→ ds_0_master ::: INSERT INTO t_order_0 VALUES (4, 4, 商品D, 1) # user_id=4 偶数 → ds_0, order_id=4 偶数 → t_order_0
# 查询:全部走 Slave
SELECT order_id,user_id,product_name,status FROM t_order
→ ds_0_slave1 ::: SELECT ... FROM t_order_0
→ ds_0_slave2 ::: SELECT ... FROM t_order_1
→ ds_1_slave1 ::: SELECT ... FROM t_order_0
→ ds_1_slave2 ::: SELECT ... FROM t_order_1
# 查询结果(4条数据全部返回)
order_id=2, user_id=2, product=商品B
order_id=4, user_id=4, product=商品D
order_id=1, user_id=1, product=商品A
order_id=3, user_id=3, product=商品C
验证结论:
| 验证项 | 预期 | 实际结果 |
|---|---|---|
| 分库:user_id 偶数 → ds_0 | ds_0_master |
✅ |
| 分库:user_id 奇数 → ds_1 | ds_1_master |
✅ |
| 分表:order_id 偶数 → t_order_0 | t_order_0 |
✅ |
| 分表:order_id 奇数 → t_order_1 | t_order_1 |
✅ |
| 读写分离:INSERT → Master | Master 节点 | ✅ |
| 读写分离:SELECT → Slave | Slave 节点 | ✅ |
| 数据完整性 | 4条数据全量返回 | ✅ |
六、Proxy 与 JDBC 对比总结
| 对比维度 | ShardingSphere-Proxy | ShardingSphere-JDBC |
|---|---|---|
| 部署方式 | Docker 独立容器 | 引入 Maven 依赖 |
| 配置位置 | global.yaml + database-*.yaml |
application.yml + sharding-config.yaml |
| 分片配置 | dataSourceGroups(5.5.x) |
同 Proxy 语法 |
| JDBC 驱动 | Proxy 内置 | ShardingSphereDriver + jdbc:shardingsphere:classpath: |
| 版本兼容 | 独立发布 | 需与 Spring Boot snakeyaml 版本匹配 |
| 运维 | 单独管理 Proxy 容器 | 随应用部署 |
| 性能 | 多一次网络跳转 | 直连数据库 |
| 适用 | 多应用共享分片规则 | 单个应用需要分片 |
七、总结
通过本文,你用 ShardingSphere-JDBC 完成了:
| 目标 | 状态 |
|---|---|
| 搭建 Spring Boot 4.0.7 + ShardingSphere-JDBC 项目 | ✅ |
通过 ShardingSphereDriver 加载分片配置 |
✅ |
实现 user_id % 2 分库 |
✅ |
实现 order_id % 2 分表 |
✅ |
| 实现读写分离(写 Master / 读 Slave) | ✅ |
| JUnit 验证分片与路由正确性 | ✅ |
下一步建议:
- 接入分布式主键(Snowflake 算法)
- 配置分片事务(
@ShardingSphereTransaction) - 分片 + 加密规则组合使用

浙公网安备 33010602011771号