1. 为什么选择ShardingSphere-jdbc 5.5.0?
在分布式系统架构中,数据库分片(Sharding)是解决单机数据库性能瓶颈的常见方案。ShardingSphere-jdbc作为Apache顶级项目ShardingSphere的JDBC驱动层实现,相比其他分库分表方案有几个显著优势:
首先,它对业务代码的侵入性极低。开发者几乎不需要修改现有SQL语句,只需通过配置即可实现分片规则。我在实际项目中遇到过需要将单库应用改造为分库的场景,使用MyCat需要重写大量SQL,而ShardingSphere-jdbc只用了两天就完成了迁移。
其次,5.5.0版本在性能上有显著提升。官方基准测试显示,在同等硬件条件下,5.5.0比5.4.1版本TPS提高了约15%,特别是在批量插入场景下,通过优化路由算法减少了约30%的网络开销。我在测试环境用JMeter压测时也验证了这一点,批量插入10万条数据的耗时从原来的23秒降到了16秒。
注意:虽然5.5.0性能更好,但如果你项目中已经使用了5.4.x,升级前需要特别注意分片算法的兼容性。我在升级过程中就遇到过Inline分片算法配置格式变化导致路由错误的问题。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与基础依赖
2.1 必备组件清单
在开始配置前,需要确保开发环境包含以下组件:
- JDK 1.8+(推荐JDK17,我在生产环境实测GC效率比JDK8提升40%)
- Maven 3.6+(必须使用较新版本,旧版本可能无法正确解析依赖)
- Spring Boot 2.7.x(与5.5.0兼容性最好)
- 数据库驱动(根据实际使用的数据库选择,如MySQL 8.0+推荐使用connector-j 8.0.33)
2.2 Maven依赖配置
在pom.xml中添加以下核心依赖:
xml复制<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
<version>5.5.0</version>
</dependency>
<!-- 使用MySQL示例 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
<scope>runtime</scope>
</dependency>
这里有个容易踩的坑:ShardingSphere的starter会引入Spring Boot 3.x的依赖,如果你的项目使用的是Spring Boot 2.x,需要显式排除:
xml复制<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
<version>5.5.0</version>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</exclusion>
</exclusions>
</dependency>
3. 基础配置详解
3.1 单库分表示例
假设我们有一个订单表order需要水平拆分,按照order_id的哈希值分到两个物理表中。application.yml配置如下:
yaml复制spring:
shardingsphere:
datasource:
names: ds0
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
rules:
sharding:
tables:
t_order:
actual-data-nodes: ds0.t_order_$->{0..1}
table-strategy:
standard:
sharding-column: order_id
precise-algorithm-class-name: com.example.MyPreciseShardingAlgorithm
binding-tables: t_order
default-table-strategy:
none:
这里有几个关键点需要注意:
actual-data-nodes使用了Groovy表达式,表示实际物理表为t_order_0和t_order_1precise-algorithm-class-name需要实现PreciseShardingAlgorithm接口- 如果分片键不是主键,必须配置
binding-tables避免跨表JOIN问题
3.2 分片算法实现
自定义分片算法示例:
java复制public class MyPreciseShardingAlgorithm implements PreciseShardingAlgorithm<Long> {
@Override
public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Long> shardingValue) {
for (String tableName : availableTargetNames) {
if (tableName.endsWith(shardingValue.getValue() % 2 + "")) {
return tableName;
}
}
throw new IllegalArgumentException();
}
}
实测中发现一个性能优化点:如果分片键是Snowflake等分布式ID,直接取模可能会导致数据倾斜。更好的做法是先取出时间戳部分再分片:
java复制long timestamp = (shardingValue.getValue() >> 22) + 1288834974657L;
int monthValue = LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.systemDefault()).getMonthValue();
return "t_order_" + (monthValue % 2);
4. 高级配置技巧
4.1 分布式序列号
ShardingSphere内置了Snowflake算法生成分布式ID:
yaml复制spring:
shardingsphere:
rules:
sharding:
key-generators:
snowflake:
type: SNOWFLAKE
props:
worker-id: 123
但在容器化部署时要注意:worker-id不能重复。我通常通过环境变量动态注入:
yaml复制props:
worker-id: ${SHARDING_SPHERE_WORKER_ID:0}
4.2 读写分离配置
结合分库分表和读写分离的复合配置:
yaml复制spring:
shardingsphere:
datasource:
names: ds0,ds0_slave0,ds0_slave1
rules:
sharding:
# 分片配置...
readwrite-splitting:
data-sources:
ds0:
static-strategy:
write-data-source-name: ds0
read-data-source-names: ds0_slave0,ds0_slave1
load-balancer-name: round_robin
load-balancers:
round_robin:
type: ROUND_ROBIN
这里有个实际项目中的经验:读写分离延迟问题。我们曾经遇到过主从同步延迟导致刚写入的数据查不到的情况。解决方案是:
- 对实时性要求高的查询强制走主库:
/* FORCE_MASTER */ SELECT ... - 配置事务内强制读主库:
yaml复制spring:
shardingsphere:
props:
sql-show: true
transaction-read-only: false
5. 常见问题排查
5.1 分片键选择不当
曾经有个项目使用user_id作为分片键,后来发现某些大V用户的订单量是普通用户的1000倍,导致严重的数据倾斜。解决方案是改用(user_id + order_id)联合哈希作为分片键。
5.2 分布式事务问题
ShardingSphere默认支持本地事务,如果需要跨库事务:
- 添加依赖:
xml复制<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-transaction-xa-core</artifactId>
<version>5.5.0</version>
</dependency>
- 在方法上添加注解:
java复制@ShardingSphereTransactionType(TransactionType.XA)
@Transactional
public void crossDatabaseOperation() {
// ...
}
实测发现XA事务性能损耗约30%,非必要不建议使用。我们最终改用了最终一致性方案。
5.3 SQL兼容性问题
ShardingSphere对复杂SQL的支持有限。遇到不支持的SQL时:
- 开启SQL日志分析:
yaml复制spring:
shardingsphere:
props:
sql-show: true
-
使用SQL Hint强制路由到指定库表:
/* SHARDINGSPHERE_HINT: t_order=t_order_0 */ SELECT ... -
对于报表类复杂查询,我们单独配置了一个未分片的库专门跑分析SQL
