★ 分布式事务方案如何取舍?Seata AT 模式原理是什么?

结论先行:跨服务写多个库无法用单库事务,常见方案按“一致性强度 vs 吞吐/侵入”分档:XA(数据库层 2PC,强一致但阻塞)、Seata AT(无侵入自动补偿,业界主流)、TCC(业务补偿,高吞吐但侵入大)、Saga/本地消息表(最终一致,适合长流程)。Seata AT 的核心是“一阶段本地提交 + 二阶段反向补偿”,借助全局锁与 undo_log 实现近似强一致。

一、方案对比

方案一致性吞吐业务侵入适用
XA 2PC低(资源锁到全局提交)同库技术栈、短事务
Seata AT较强(最终一致+锁控制)低(注解即可)多服务多库常规事务
TCC最终一致高(Try/Confirm/Cancel 三方法)高并发、资源预留
Saga最终一致中(需补偿)长流程、无强一致

二、Seata 角色与 AT 模式流程

角色职责
TC(事务协调器)独立服务,管理全局事务状态
TM(事务管理器)业务入口,开启/提交/回滚全局事务
RM(资源管理器)各分支数据源,注册分支并执行本地事务
@GlobalTransactional // TM:开启全局事务(seata-all/spring-cloud-starter-alibaba-seata)
public void createOrder() {
    orderService.insert();   // RM1:分支一
    stockService.deduct();   // RM2:分支二
}

AT 两阶段:

  1. 一阶段:RM 解析业务 SQL,生成 undo_log(before/after 镜像),本地事务提交并注册分支,同时按主键加全局锁
  2. 二阶段提交:TC 通知各 RM 异步清理 undo_log,释放全局锁;
  3. 二阶段回滚:RM 依据 undo_log 反向生成补偿 SQL(把数据恢复为 before 镜像),校验 after 未被他事务改过才回滚,防止脏写。

三、选型与取舍要点

  • 每个业务库需建 undo_log 表;SQL 需能被解析(带主键的常规 CRUD),复杂 DDL/不走 SQL 的变更不支持;
  • 全局锁影响并发:热点行写冲突会等待/失败,超高并发写场景谨慎;
  • AT 也非完全无感:慢 SQL、长事务、大批量更新会放大锁与日志开销;
  • 高并发写 + 可接受补偿设计 → 优先 TCC/Saga;简单跨库事务、并发可控 → AT 性价比最高。

常见追问 / 记忆点

  • 追问:AT 与 XA 最大区别?答:XA 一阶段不提交、锁到全局结束;AT 一阶段就本地提交,靠 undo_log 与全局锁做补偿,锁窗口小、吞吐更高。
  • 追问:什么时候不该上分布式事务框架?答:能通过接口幂等 + 对账/重试达到最终一致时,尽量别引全局事务,成本和风险更低。
  • 记忆点:TC/TM/RM 三角色;一阶段提交 + undo_log 补偿 + 全局锁防脏写 = AT。
笔记加载中…