Seata实战指南:AT/TCC/SAGA模式详解与微服务集成

一、AT模式使用:自动补偿型事务

1. 快速接入

在Spring Boot项目中引入依赖:

<dependency>
    <groupId>io.seata</groupId>
    <artifactId>seata-spring-boot-starter</artifactId>
    <version>最新版本</version>
</dependency>

2. 关键配置示例

seata:
  enabled: true
  application-id: order-service
  tx-service-group: my_tx_group  # 事务分组需与seata-server配置匹配
  service:
    vgroup-mapping:
      my_tx_group: default       # 映射到Seata Server集群
  config:
    type: nacos                  # 配置中心类型
  registry:
    type: nacos                  # 注册中心类型
  store:
    mode: db                     # 事务日志存储模式(可选file/db/redis)

3. 业务代码示例

@Service
public class OrderService {
    
    @GlobalTransactional(timeoutMills = 300000, name = "createOrder")
    public void createOrder(OrderDTO order) {
        // 1. 扣减库存
        stockFeignClient.deduct(order.getProductId(), order.getCount());
        
        // 2. 创建订单
        orderMapper.insert(order);
        
        // 3. 扣减账户余额
        accountFeignClient.debit(order.getUserId(), order.getMoney());
    }
}

实践建议:

  • 事务超时时间根据业务复杂度合理设置
  • 事务分组名称建议按业务领域划分
  • 生产环境推荐使用DB存储模式保证可靠性

二、TCC模式实现:精细化控制

1. 接口定义规范

@LocalTCC
public interface AccountService {
    @TwoPhaseBusinessAction(name = "deduct", commitMethod = "confirm", rollbackMethod = "cancel")
    boolean tryDeduct(@BusinessActionContextParameter(paramName = "userId") String userId,
                     @BusinessActionContextParameter(paramName = "money") BigDecimal money);
    
    boolean confirm(BusinessActionContext context);
    
    boolean cancel(BusinessActionContext context);
}

2. 业务实现要点

@Service
public class AccountServiceImpl implements AccountService {
    
    @Transactional
    @Override
    public boolean tryDeduct(String userId, BigDecimal money) {
        // 检查资源可用性
        Account account = accountMapper.selectById(userId);
        if (account.getBalance().compareTo(money) < 0) {
            throw new RuntimeException("余额不足");
        }
        
        // 冻结金额(Try阶段)
        account.setFrozen(account.getFrozen().add(money));
        accountMapper.updateById(account);
        return true;
    }
    
    @Override
    public boolean confirm(BusinessActionContext context) {
        // 实际扣款(Confirm阶段)
        String userId = (String) context.getActionContext("userId");
        BigDecimal money = (BigDecimal) context.getActionContext("money");
        return accountMapper.confirmDeduct(userId, money) > 0;
    }
    
    @Override
    public boolean cancel(BusinessActionContext context) {
        // 释放冻结金额(Cancel阶段)
        String userId = (String) context.getActionContext("userId");
        BigDecimal money = (BigDecimal) context.getActionContext("money");
        return accountMapper.cancelDeduct(userId, money) > 0;
    }
}

异常处理机制:

图1

实践建议:

  • Try阶段必须实现幂等性
  • Confirm/Cancel阶段必须保证成功
  • 建议使用@BusinessActionContextParameter明确参数映射关系

三、SAGA模式:长事务解决方案

1. 状态机配置示例

{
  "Name": "purchaseFlow",
  "Steps": [
    {
      "Name": "reduceInventory",
      "Compensate": "compensateInventory",
      "ServiceName": "inventoryService",
      "ServiceMethod": "reduce"
    },
    {
      "Name": "createOrder",
      "Compensate": "compensateOrder",
      "ServiceName": "orderService",
      "ServiceMethod": "create"
    }
  ]
}

2. 补偿服务实现

@Service
public class InventoryService {
    
    public void reduce(String productId, int count) {
        // 扣减库存逻辑
    }
    
    public void compensateInventory(String productId, int count) {
        // 恢复库存逻辑
        System.out.println("执行库存补偿操作");
    }
}

执行流程:

图2

实践建议:

  • 适用于业务流程长、可接受最终一致性的场景
  • 补偿服务必须实现幂等
  • 建议每个步骤设置合理的超时时间

四、微服务框架集成

1. Spring Cloud集成要点

@FeignClient(name = "account-service")
public interface AccountFeignClient {
    
    @PostMapping("/account/debit")
    Boolean debit(@RequestParam("userId") String userId, 
                 @RequestParam("money") BigDecimal money);
}

// 自动传递XID的RestTemplate配置
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
    return new RestTemplate(new SeataRestTemplateInterceptor());
}

2. Dubbo集成配置

# provider端配置
dubbo.provider.filter=seata

# consumer端配置
dubbo.consumer.filter=seata

上下文传递原理:

图3

实践建议:

  • 确保微服务间网络可连通
  • Dubbo建议使用2.7.0以上版本
  • 跨语言调用需手动传递seata_xid请求头

五、模式选型指南

特性AT模式TCC模式SAGA模式
侵入性
一致性强一致最终一致最终一致
性能
适用场景短事务、CRUD操作需要精确控制的业务长流程、跨系统业务
开发复杂度

决策建议:

  1. 优先考虑AT模式,满足大部分业务场景
  2. 对性能敏感且能接受最终一致性的场景选择SAGA
  3. 需要精确控制事务边界的业务采用TCC

六、常见问题排查

  1. 全局事务不生效检查清单:

    • 确认@GlobalTransactional注解添加正确
    • 检查事务分组配置是否匹配
    • 验证Seata Server是否正常运行
    • 查看日志中是否有XID传递
  2. 典型错误日志分析:

    // 分支事务注册失败
    Could not register branch into global session xid:192.168.1.100:8091:12345678
    
  3. 检查undo_log表是否存在
  4. 验证数据库账号权限
  5. 确认TC集群地址配置正确

  6. 性能优化参数:

    # 客户端配置
    client.rm.report.success.enable=false  # 关闭分支执行结果上报
    client.tm.degrade.check=false         # 关闭降级检查
    
    # 服务端配置
    store.db.maxWait=5000                 # 连接池最大等待时间
    server.undo.log.save.days=7           # 缩短undo日志保留时间

评论已关闭