ShardingSphere 分库分表 后的事务
【摘要】 在 ShardingSphere 中实现分库分表后的分布式事务是一个关键挑战,因为数据被分散到多个数据库实例中,传统的本地事务无法保证跨库操作的原子性。ShardingSphere 提供了多种分布式事务解决方案,适用于不同场景。以下是详细的技术解析和配置指南: 一、ShardingSphere 分布式事务支持ShardingSphere 支持以下三种主流的分布式事务模式:模式适用场景特点XA...
在 ShardingSphere 中实现分库分表后的分布式事务是一个关键挑战,因为数据被分散到多个数据库实例中,传统的本地事务无法保证跨库操作的原子性。ShardingSphere 提供了多种分布式事务解决方案,适用于不同场景。以下是详细的技术解析和配置指南:
一、ShardingSphere 分布式事务支持
ShardingSphere 支持以下三种主流的分布式事务模式:
| 模式 | 适用场景 | 特点 |
|---|---|---|
| XA(两阶段提交) | 强一致性要求,如金融交易、订单支付等 | 基于 XA 协议,强一致性但性能较低,依赖数据库的 XA 支持 |
| SEATA(AT 模式) | 业务复杂度高、需要全局事务的场景(如订单+库存+支付) | 基于 Seata 的 AT 模式,性能较好,但需要引入 Seata 服务端 |
| SAGA | 长事务、允许最终一致性的场景(如旅游订单、工作流) | 柔性事务,通过补偿机制实现最终一致性,性能高但实现复杂 |
| 本地事务(TCC) | 适合高并发、短事务的场景(如秒杀系统) | 需要业务代码实现 Try-Confirm-Cancel,灵活性高但开发成本大 |
二、XA 分布式事务(强一致性)
1. 原理
XA 事务基于 两阶段提交(2PC) 协议,通过事务协调器(TM)和资源管理器(RM)保证跨库事务的原子性。
2. 配置步骤
(1)引入依赖
<!-- Spring Boot + ShardingSphere-JDBC -->
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
<version>5.3.2</version>
</dependency>
<!-- 数据库驱动(如 MySQL) -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
(2)配置数据源和事务
在 application.yml 中配置分库分表规则和 XA 事务:
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: password
ds1:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://localhost:3306/db1
username: root
password: password
rules:
sharding:
tables:
t_order:
actual-data-nodes: ds$->{0..1}.t_order_$->{0..1} # 分库分表规则
table-strategy:
standard:
sharding-column: order_id
precise-algorithm-class-name: com.example.OrderTableShardingAlgorithm
database-strategy:
standard:
sharding-column: user_id
precise-algorithm-class-name: com.example.OrderDatabaseShardingAlgorithm
props:
sql-show: true # 打印 SQL 日志
# 启用 XA 事务
transaction-type: XA
xa-transaction-manager-class-name: org.apache.shardingsphere.transaction.xa.AtomikosXATransactionManager
(3)代码示例
@Service
public class OrderService {
@Autowired
private JdbcTemplate jdbcTemplate;
@Transactional // 声明式事务(Spring 管理)
public void createOrder(Long userId, Long orderId) {
// 插入订单(跨库操作)
jdbcTemplate.update("INSERT INTO t_order (order_id, user_id, status) VALUES (?, ?, ?)",
orderId, userId, "CREATED");
// 更新库存(假设在另一个库)
jdbcTemplate.update("UPDATE t_inventory SET stock = stock - 1 WHERE product_id = ?",
1001);
}
}
3. 注意事项
- 性能问题:XA 事务需要全局锁,并发高时可能成为瓶颈。
- 数据库支持:MySQL 需启用
binlog_format=ROW(推荐 InnoDB 引擎)。 - 超时设置:调整
max_actives和max_timeout避免阻塞。
三、SEATA 分布式事务(AT 模式)
1. 原理
SEATA 的 AT 模式通过 全局锁 和 回滚日志 实现无侵入式的分布式事务,性能优于 XA。
2. 配置步骤
(1)部署 SEATA 服务端
- 下载 SEATA Server。
- 修改
file.conf配置存储模式(如file或MySQL)。 - 启动 SEATA Server:
sh seata-server.sh -p 8091 -h 127.0.0.1
(2)ShardingSphere 集成 SEATA
在 application.yml 中配置:
spring:
shardingsphere:
props:
transaction-type: SEATA
seata-enable-auto-data-source-proxy: true # 自动代理数据源
# 其他分库分表配置...
(3)业务代码改造
- 添加
@GlobalTransactional注解:@Service public class OrderService { @Autowired private JdbcTemplate jdbcTemplate; @GlobalTransactional // SEATA 全局事务 public void createOrder(Long userId, Long orderId) { jdbcTemplate.update("INSERT INTO t_order (...) VALUES (...)"); jdbcTemplate.update("UPDATE t_inventory SET stock = stock - 1 WHERE ..."); } } - 在
resources下添加registry.conf(注册中心配置,如 Nacos)。
3. 注意事项
- 数据源代理:需启用
seata-enable-auto-data-source-proxy。 - 表结构要求:业务表需有主键,且 SEATA 会创建
undo_log表。 - 性能优化:调整 SEATA 的
service.vgroupMapping和store.mode。
四、SAGA 柔性事务(最终一致性)
1. 原理
SAGA 通过 正向操作 + 补偿操作 实现最终一致性,适用于长事务场景。
2. 配置步骤
(1)定义 SAGA 状态机
编写 JSON 文件(如 order-saga.json):
{
"Name": "OrderSaga",
"StartState": "CreateOrder",
"States": {
"CreateOrder": {
"Type": "ServiceTask",
"ServiceName": "orderService",
"ServiceMethod": "createOrder",
"Next": "CompensateOrderOnError"
},
"CompensateOrderOnError": {
"Type": "ServiceTask",
"ServiceName": "orderService",
"ServiceMethod": "compensateOrder",
"IsCompensation": true
}
}
}
(2)集成 ShardingSphere
在 application.yml 中配置:
spring:
shardingsphere:
props:
transaction-type: SAGA
saga-state-machine-path: classpath:order-saga.json
3. 适用场景
- 订单超时取消
- 旅游套餐预订(涉及酒店、机票、保险等多个服务)
五、本地事务(TCC)
1. 原理
TCC(Try-Confirm-Cancel)通过业务代码实现两阶段提交:
- Try:预留资源(如冻结库存)。
- Confirm:确认操作(如实际扣减库存)。
- Cancel:回滚操作(如释放冻结库存)。
2. 代码示例
public interface TccOrderService {
@Transactional
boolean tryOrder(Long orderId); // 预留资源
@Transactional
boolean confirmOrder(Long orderId); // 确认提交
@Transactional
boolean cancelOrder(Long orderId); // 回滚
}
3. 适用场景
- 秒杀系统(高并发、短事务)
- 支付系统(需要精确控制资源)
六、性能对比与选型建议
| 模式 | 一致性 | 性能 | 实现复杂度 | 适用场景 |
|---|---|---|---|---|
| XA | 强一致 | 低 | 低 | 金融交易 |
| SEATA | 强一致 | 中 | 中 | 订单+库存+支付 |
| SAGA | 最终一致 | 高 | 高 | 旅游订单、工作流 |
| TCC | 最终一致 | 极高 | 极高 | 秒杀、高并发支付 |
推荐选型:
- 优先 SEATA:平衡一致性与性能,适合大多数业务。
- 高并发场景选 TCC:如秒杀系统。
- 长事务选 SAGA:如旅游订单。
七、常见问题与排查
1. XA 事务超时
- 原因:网络延迟或数据库锁等待。
- 解决:调整
max_actives和max_timeout:spring: shardingsphere: props: xa-transaction-manager-class-name: org.apache.shardingsphere.transaction.xa.AtomikosXATransactionManager max-actives: 200 max-timeout: 300000 # 5分钟
2. SEATA 报错 No available service
- 原因:SEATA Server 未注册或网络不通。
- 解决:
- 检查 SEATA Server 日志。
- 确认
registry.conf配置正确(如 Nacos 地址)。
3. 分库分表后事务不生效
- 原因:未正确配置
transaction-type。 - 解决:检查
application.yml是否包含:spring: shardingsphere: props: transaction-type: XA # 或 SEATA/SAGA
八、总结
- XA:简单但性能低,适合强一致性场景。
- SEATA:平衡性能与一致性,推荐作为首选方案。
- SAGA/TCC:适合柔性事务或高并发场景,但实现复杂。
通过合理选择事务模式,可以确保 ShardingSphere 分库分表后的数据一致性,同时兼顾系统性能。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)