分布式事务实战: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/