Seata实现分布式事务

以下是使用 Seata 实现分布式事务管理的详细步骤及代码示例,结合其 AT 模式(自动补偿模式)进行说明:


一、环境准备

  1. 部署 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
      
  2. 业务数据库准备
    在每个业务数据库中创建 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 模式执行流程

  1. 第一阶段(提交前)

    • Seata 代理数据源,解析 SQL 并生成 before_image(前镜像)和 after_image(后镜像),写入 undo_log 表。
    • 向 TC 注册分支事务,锁定全局数据。
    • 提交本地事务(业务数据与 undo_log 一并提交)。
  2. 第二阶段(提交/回滚)

    • 提交:TC 通知所有 RM 异步删除 undo_log
    • 回滚:TC 通知 RM 根据 undo_log 生成反向 SQL 恢复数据,并删除日志。

五、注意事项

  1. 全局锁冲突
    AT 模式依赖全局锁,高并发场景可能引发锁竞争,可通过调整锁超时时间或切换为 TCC 模式优化。
  2. 幂等性处理
    远程服务需支持幂等(如通过唯一业务 ID),避免重复提交。
  3. 异常传递
    业务代码需显式抛出异常触发回滚,避免 try-catch 吞没异常。
  4. 版本兼容性
    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 模式

  1. 定义 TryConfirmCancel 接口。
  2. 实现资源预留(Try)、提交确认(Confirm)和补偿回滚(Cancel)逻辑。

总结

Seata 的 AT 模式 通过代理数据源和自动生成回滚日志,显著降低了分布式事务的侵入性,适合中小型系统快速集成。关键步骤包括部署 TC、配置 Client、添加 @GlobalTransactional 注解及处理幂等性。实际应用中需结合业务场景选择事务模式,并通过监控和日志优化系统健壮性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值