分布式事务实战:Seata AT模式与TCC模式选型与落地指南

分布式事务实战:Seata AT 与 TCC 模式选型与落地

后端开发(微服务架构)中,分布式事务是跨服务数据一致性的核心难点。Seata 是目前国内使用最广的分布式事务框架,提供 AT、TCC、Saga 与 XA 四种模式。AT 模式对业务侵入最小,基于全局事务锁与 undo_log 实现回滚;TCC 模式需要业务方实现 Try/Confirm/Cancel 三阶段接口,适合对一致性要求高、需要冻结资源的场景。本文对比两种模式的使用方法与适用边界,并给出实际部署配置。

Seata AT 模式原理与集成配置

AT 模式依赖数据库事务,业务侧只要配置好全局事务注解即可。事务发起方加 @GlobalTransactional,分支事务注册到 Seata Server;提交时 Seata 执行两阶段提交,回滚时根据 undo_log 生成反向 SQL 恢复数据。AT 模式要求数据库支持本地事务与全局锁,MySQL 5.7+ 直接可用。集成步骤:下载 seata-server、配置注册中心、业务表加 undo_log 表、引入 seata-spring-boot-starter。

seata:
  enabled: true
  application-id: order-service
  tx-service-group: my_tx_group
  registry:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      namespace: public
  config:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848

分布式事务 TCC 模式的 Try-Confirm-Cancel 实现

TCC 把业务逻辑拆成三个阶段:Try 阶段检查并冻结资源(余额冻结、库存预占),Confirm 阶段确认执行,Cancel 阶段释放冻结。业务侵入性强但一致性与性能最好。注意冻结资源要写业务表状态字段而非加锁,防止长时间锁住记录。Seata 提供 @TwoPhaseBusinessAction 注解标识 Try 方法,name 属性需全局唯一,对应 ConfirmMethod 与 CancelMethod。

@TwoPhaseBusinessAction(name = "deductBalance", commitMethod = "confirm", rollbackMethod = "cancel")
public boolean try(DeductBalanceContext ctx) {
    // Try:冻结金额
    accountMapper.freeze(ctx.getUserId(), ctx.getAmount());
    return true;
}
public boolean confirm(DeductBalanceContext ctx) {
    // Confirm:扣减冻结金额
    return accountMapper.deduct(ctx.getUserId(), ctx.getAmount());
}
public boolean cancel(DeductBalanceContext ctx) {
    // Cancel:解冻金额
    return accountMapper.unfreeze(ctx.getUserId(), ctx.getAmount());
}

AT 与 TCC 模式对比与选型建议

数据一致性要求高、业务逻辑简单、希望改动少的场景选 AT;业务链路长、涉及资金与库存、需要冻结语义的场景选 TCC。TCC 实现成本高(每接口需三套方法),对业务模型入侵大,且必须处理空回滚与悬挂问题,建议只在核心链路使用。除 Seata 外,也有 dtm、ByteTCC 等方案;微服务架构中很多场景可以用本地消息表 + 消息中间件重试代替分布式事务,先考虑业务能否最终一致,减少强一致锁带来的性能损耗。

分布式事务测试与故障演练

分布式事务上线前必须做故障演练。模拟分支事务失败(数据库断连、异常抛出)、网络超时、事务超时,验证全局事务是否按预期回滚。Seata 事务统计信息可在 Dashboard 查看,检查全局事务成功率、分支事务失败原因。演练脚本建议自动化,纳入 CI 回归流程。另一个重点:事务超时配置要与接口耗时匹配,过短会导致正常慢接口误回滚,过长会在链路堆积,按业务 99 分位耗时 ×2 设置。

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

赞 (0)
小编小编
上一篇 2026年9月16日
下一篇 2026年9月16日

相关推荐

分布式事务实战:Seata AT模式与TCC模式选型落地

微服务拆分后,跨库跨服务的数据一致性成为绕不开的问题,单体时代的本地事务不再适用。Seata提供AT、TCC、Saga、XA四种模式,其中AT与TCC在业务项目中使用最广。本文对比两种模式的使用方式与适用边界,给出可落地的接入示例。

AT模式:无侵入的自动补偿方案

AT模式对业务代码几乎零侵入:在数据源上包一层代理,分支事务执行前后自动记录undo log快照,回滚时反向补偿。典型用法:

// 引入 seata-spring-boot-starter 并配置数据源代理
@GlobalTransactional(timeoutMills = 30000)
public void createOrder(OrderDTO dto) {
    orderMapper.insert(dto);                 // 本地事务
    stockService.deduct(dto.getSkuId(), 1);  // 远程调用
    couponService.use(dto.getCouponId());
}

@GlobalTransactional标注的入口方法即全局事务起点,分支事务由TC协调二阶段提交。业务方法里不需要写任何补偿逻辑,回滚由undo_log自动完成。

AT模式的代价与适用边界

AT模式适合同一事务内数据一致性要求高、并发冲突概率低的场景。两点限制要先确认:

  • 全局锁:二阶段提交期间对冲突数据加锁,热点商品并发扣减可能放大延迟;
  • 隔离级别:默认读未提交,需要自定义隔离时要在查询上加 SELECT FOR UPDATE 或标记 @GlobalLock。

订单创建、账户积分、库存扣减这类业务,AT模式的成本明显低于手写补偿。

TCC模式:手工补偿控制业务流程

当业务流程中间态必须对外可见、分支事务需要长期持有时,用TCC把每个操作拆成Try、Confirm、Cancel三个阶段:

@TwoPhaseBusinessAction(name = "deductStock",
    commitMethod = "confirm", rollbackMethod = "cancel")
public void deduct(BusinessActionContext ctx, Long skuId, int num) {
    // Try:冻结库存,不直接扣减
    stockMapper.freezeStock(skuId, num);
}

public boolean confirm(BusinessActionContext ctx) {
    // Confirm:冻结转实际扣减,最终提交
    return stockMapper.confirmFreeze(skuId, num);
}

public boolean cancel(BusinessActionContext ctx) {
    // Cancel:解冻恢复
    return stockMapper.releaseFreeze(skuId, num);
}

TCC需要业务方自己保证幂等与资源释放,实现成本比AT高,但适合预占资金、扣减积分、订座等强一致性场景。

两种模式的选型对比

维度 AT模式 TCC模式
侵入性 低,代理数据源即可 高,需拆三个阶段
一致性 最终一致 强一致(资源冻结)
典型场景 订单、库存、积分 资金预占、行程订座
失败恢复 undo自动回滚 人工确认补偿

另一条思路是能不用就不用:事务边界跨越的服务,优先通过幂等接口加本地消息表实现最终一致性,把分布式事务的数量压到极少数,Seata只用于真正强一致的短链路。

生产落地注意事项

Seata服务端(TC)需独立部署并持久化事务日志;客户端事务分组要与服务端配置一致。全局事务超时按最慢链路加余量设置,避免慢接口拖死全局锁。上线前做一次故障演练:kill掉一个分支实例,观察二阶段协调与undo日志是否正常工作。

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

赞 (0)
小编小编
上一篇 2026年9月14日
下一篇 2026年9月14日

相关推荐