分布式事务后端开发实战:Seata AT模式与TCC补偿机制

微服务架构下,一个用户下单操作同时涉及订单、库存、账户三个服务,每个服务各自拥有数据库,本地事务无法跨服务生效。分布式事务用来解决这类跨服务数据一致性问题,Seata是目前使用率较高的中间件。本文对比其AT模式与TCC补偿模式,并给出可直接参考的后端实现代码。

Seata核心组件与部署

Seata由三部分组成:TC事务协调器、TM事务管理器、RM资源管理器。TM向TC申请全局事务,RM管理本地事务分支。

docker run -d --name seata-server \
  -p 8091:8091 \
  -e SEATA_IP=192.168.1.10 \
  seataio/seata-server:2.0.0

业务服务引入seata-spring-boot-starter,配置事务分组与TC地址后即可接入。

# application.yml
seata:
  enabled: true
  application-id: order-service
  tx-service-group: my_tx_group
  registry:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848

AT模式实现与原理

AT模式对业务侵入最低,数据源代理自动记录分支事务的undo log,全局回滚时反向补偿。核心是全局事务范围加@GlobalTransactional注解。

@Service
public class OrderService {

    @GlobalTransactional(timeoutMills = 360000)
    public void createOrder(OrderDTO dto) {
        orderMapper.insert(buildOrder(dto));   // 本地事务1
        stockClient.deductStock(dto);          // 远程事务2
        accountClient.debit(dto.getAmount());  // 远程事务3
    }
}

AT模式要求业务表存在并维护UNDO_LOG表,且所有参与方都经过Seata数据源代理。适用普通业务场景,性能上会多一次undo日志写入。

TCC补偿机制实现

TCC把事务拆成Try、Confirm、Cancel三个阶段,适合对一致性要求高、不允许脏读的金融链路。参与者需要自己编写补偿逻辑。

@LocalTCC
public interface AccountTCCService {

    @TwoPhaseBusinessAction(
        name = "debitAccount",
        commitMethod = "commit",
        rollbackMethod = "cancel"
    )
    boolean tryDebit(@BusinessActionContextParameter(paramName = "userId") Long userId,
                     @BusinessActionContextParameter(paramName = "amount") BigDecimal amount);

    boolean commit(BusinessActionContext ctx);
    boolean cancel(BusinessActionContext ctx);
}
@Service
public class AccountTCCServiceImpl implements AccountTCCService {

    @Override
    public boolean tryDebit(Long userId, BigDecimal amount) {
        // 冻结资金,写入冻结表
        return freezeService.freeze(userId, amount) > 0;
    }

    @Override
    public boolean commit(BusinessActionContext ctx) {
        // 冻结转扣款,需幂等
        return accountDao.confirmDebit(ctx.getActionContext("userId"),
                (BigDecimal) ctx.getActionContext("amount"));
    }

    @Override
    public boolean cancel(BusinessActionContext ctx) {
        // 解冻资金,需幂等
        return freezeService.unfreeze(ctx.getActionContext("userId"),
                (BigDecimal) ctx.getActionContext("amount"));
    }
}

Confirm和Cancel必须幂等,Seata默认重试3次,接口设计上要保证重复调用结果一致。

AT与TCC模式选型对比

维度 AT模式 TCC模式
侵入性 低,无业务代码改造 高,需实现补偿接口
一致性 最终一致,即时性一般 最终一致,二阶段显式可控
性能 中等,有undo日志开销 较高,无锁表快照
适用场景 普通业务跨库操作 金融、库存等强一致链路

业务上优先AT降低开发成本,链路要求严格即时回滚的环节切换TCC。无论哪种模式,都要把幂等、超时、重试做到位,分布式事务才不会成为故障放大器。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/fen-bu-shi-shi-wu-hou-duan-kai-fa-shi-zhan-seataat-mo-shi/

(0)
小编小编
上一篇 7小时前
下一篇 7小时前

相关推荐