以下是使用 Seata 实现分布式事务管理的详细步骤及代码示例,结合其 AT 模式(自动补偿模式)进行说明:
一、环境准备
-
部署 Seata Server(TC)
- 下载 Seata Server(推荐 1.6.x 版本)并解压。
- 配置存储模式(推荐
db
模式,高可用):# conf/application.yml seata: store: mode: db db: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/seata?useSSL=false username: root password: root
- 创建 Seata Server 所需的数据库表(
global_table
,branch_table
,lock_table
)。 - 启动 Seata Server:
sh bin/seata-server.sh -p 8091 -m db
-
业务数据库准备
在每个业务数据库中创建undo_log
表,用于数据回滚(快照表):CREATE TABLE `undo_log` ( `id` BIGINT NOT NULL AUTO_INCREMENT, `branch_id` BIGINT NOT NULL, `xid` VARCHAR(100) NOT NULL, `rollback_info` LONGBLOB NOT NULL, `log_status` INT NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`) );
二、项目集成 Seata Client
1. 添加依赖
在 Spring Boot 项目的 pom.xml
中引入 Seata 依赖:
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
2. 配置文件
在 application.yml
中配置 Seata 客户端:
seata:
enabled: true
application-id: order-service
tx-service-group: my_tx_group # 事务组名,需与TC配置一致
service:
vgroup-mapping:
my_tx_group: default # 映射到TC集群
registry:
type: nacos # 注册中心类型
nacos:
server-addr: 127.0.0.1:8848
config:
type: nacos # 配置中心类型
3. 数据源代理
Seata 通过代理数据源实现 SQL 解析和自动补偿。若使用 seata-spring-boot-starter
,数据源代理默认开启,无需额外配置。
三、代码实现
1. 开启全局事务
在发起分布式事务的方法上添加 @GlobalTransactional
注解:
@Service
public class OrderService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private StockFeignClient stockFeignClient;
@GlobalTransactional // 开启全局事务
public void createOrder(Order order) {
// 1. 本地事务:创建订单
orderMapper.insert(order);
// 2. 远程调用:扣减库存
stockFeignClient.decreaseStock(order.getProductId(), order.getQuantity());
// 若任意步骤失败,Seata自动回滚
}
}
2. Feign 客户端配置
确保 Feign 支持事务上下文传递(禁用 Hystrix):
feign:
hystrix:
enabled: false
3. 分支事务处理
远程服务(如库存服务)无需显式标记分支事务,Seata 自动通过数据源代理管理本地事务。
四、AT 模式执行流程
-
第一阶段(提交前)
- Seata 代理数据源,解析 SQL 并生成
before_image
(前镜像)和after_image
(后镜像),写入undo_log
表。 - 向 TC 注册分支事务,锁定全局数据。
- 提交本地事务(业务数据与
undo_log
一并提交)。
- Seata 代理数据源,解析 SQL 并生成
-
第二阶段(提交/回滚)
- 提交:TC 通知所有 RM 异步删除
undo_log
。 - 回滚:TC 通知 RM 根据
undo_log
生成反向 SQL 恢复数据,并删除日志。
- 提交:TC 通知所有 RM 异步删除
五、注意事项
- 全局锁冲突
AT 模式依赖全局锁,高并发场景可能引发锁竞争,可通过调整锁超时时间或切换为 TCC 模式优化。 - 幂等性处理
远程服务需支持幂等(如通过唯一业务 ID),避免重复提交。 - 异常传递
业务代码需显式抛出异常触发回滚,避免try-catch
吞没异常。 - 版本兼容性
Seata 版本需与 Spring Boot、Spring Cloud Alibaba 版本匹配。
六、完整示例代码结构
├── order-service # 订单服务
│ ├── src/main/java
│ │ └── com/example/order
│ │ ├── controller/OrderController.java
│ │ ├── service/OrderService.java
│ │ └── config/SeataConfig.java
│ └── application.yml
├── stock-service # 库存服务
│ ├── src/main/java
│ │ └── com/example/stock
│ │ ├── controller/StockController.java
│ │ └── service/StockService.java
│ └── application.yml
七、扩展:TCC 模式
若业务需要更细粒度控制(如资金转账),可切换至 TCC 模式:
- 定义
Try
、Confirm
、Cancel
接口。 - 实现资源预留(Try)、提交确认(Confirm)和补偿回滚(Cancel)逻辑。
总结
Seata 的 AT 模式 通过代理数据源和自动生成回滚日志,显著降低了分布式事务的侵入性,适合中小型系统快速集成。关键步骤包括部署 TC、配置 Client、添加 @GlobalTransactional
注解及处理幂等性。实际应用中需结合业务场景选择事务模式,并通过监控和日志优化系统健壮性。