深度解析 Seata 分布式事务四大模式:XA/AT/TCC/Saga 原理、实现与 SpringBoot 实战避坑
摘要: 本文从核心原理、代码实现、优缺点及适用场景出发,系统剖析 Seata 分布式事务的 XA、AT、TCC、Saga 四大模式。并结合 SpringBoot 客户端实践,总结生产环境中的关键配置、常见问题与避坑指南,帮助开发者精准选型、高效落地。
一、Seata 概述
Seata 是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务。其核心架构由三大角色构成:
- TC (Transaction Coordinator):事务协调者,维护全局和分支事务的状态,驱动全局事务提交或回滚。
- TM (Transaction Manager):事务管理器,定义全局事务的边界,开启、提交或回滚全局事务。
- RM (Resource Manager):资源管理器,管理分支事务处理的资源,向 TC 注册分支事务,上报分支状态,并驱动分支的提交或回滚。
Seata 提供了 XA、AT、TCC、Saga 四种事务模式,以应对不同业务场景对一致性、性能和侵入性的需求。
二、XA 模式:强一致性标准实现
1. 核心原理
XA 模式基于 X/Open XA 标准两阶段提交协议 (2PC),是严格的 强一致性 事务方案。
- 一阶段 (Prepare):RM 执行业务 SQL,但不提交本地事务,仅锁定资源并向 TC 汇报成功状态。
- 二阶段 (Commit/Rollback):
- 所有分支成功 → TC 下发
COMMIT,所有 RM 提交本地事务,释放锁。 - 任一分支失败 → TC 下发
ROLLBACK,所有 RM 回滚本地事务。
3.优缺点
-
- 优点
- ✅ 标准兼容:支持 MySQL、Oracle 等所有主流 XA 数据库。
- ✅ 零业务侵入:无需修改业务逻辑,仅需配置。
- ✅ 强一致性 (ACID):数据绝对可靠,适合金融核心场景。
- 缺点
- ❌ 数据库依赖:仅限支持 XA 协议的关系型数据库。
- ❌ 阻塞风险:协调过程同步阻塞,易产生单点瓶颈。
- ❌ 性能极差:一阶段长期锁定数据库资源,并发能力低。
- 优点
-
4. 适用场景
对数据一致性要求极高(如金融交易、账务结算)、并发量较低、事务耗时短的核心业务场景。
-
三、AT 模式:无侵入自动事务(默认首选)
1. 核心原理
AT 是 Seata 默认模式,基于 本地事务 + undo log 快照 实现的最终一致性方案,对业务零侵入。
- 一阶段:
- RM 拦截业务 SQL,生成前镜像 (Before Image)。
- 执行本地事务并提交(立即释放数据库锁,高性能关键)。
- 生成后镜像 (After Image),插入
undo_log表,注册分支事务。
- 二阶段:
- 提交:异步删除
undo_log,无业务感知。 - 回滚:通过
undo_log生成反向 SQL,自动恢复数据至一阶段前状态。
- 提交:异步删除
- 一阶段:
- 所有分支成功 → TC 下发
3. 优缺点
- 优点
- ✅ 零侵入:注解驱动,业务代码无感知。
- ✅ 高性能:本地事务一阶段提交,无长锁等待。
- ✅ 易用性:开箱即用,开发成本最低。
- 缺点
- ❌ 最终一致性:存在短暂的 “中间状态”(读未提交)。
- ❌ 依赖关系型数据库:需支持
undo_log与本地事务。 - ❌ 隔离性有限:通过全局锁防止脏写,但无法防止脏读。
4. 适用场景
绝大多数微服务通用场景(如电商下单、支付),追求开发效率与性能平衡的首选方案。
四、TCC 模式:高性能业务定制事务
1. 核心原理
TCC (Try-Confirm-Cancel) 是业务侵入式的柔性事务,将事务拆分为三个阶段,完全由业务代码控制,无数据库锁,性能最高。
- Try:预留 / 冻结资源(如冻结库存、冻结余额),完成业务检查。
- Confirm:确认提交,使用预留资源执行业务(如扣减冻结库存)。
- Cancel:取消回滚,释放预留资源(如解冻库存)。
2. SpringBoot 实现(接口 + 实现分离)
核心规则:必须接口 + 实现分离,
@LocalTCC写在接口上。
(1) 定义 TCC 接口
@LocalTCC // 必须在接口
public interface StorageTccService {
@TwoPhaseBusinessAction(
name = "tryDeduct",
commitMethod = "confirm", // 指定Confirm方法
rollbackMethod = "cancel" // 指定Cancel方法
)
boolean tryDeduct(
@BusinessActionContextParameter("productId") String productId,
@BusinessActionContextParameter("count") Integer count
);
boolean confirm(BusinessActionContext context);
boolean cancel(BusinessActionContext context);
}
(2) 实现类(核心)
@Service
public class StorageTccServiceImpl implements StorageTccService {
@Autowired
private StorageMapper storageMapper;
@Autowired
private StorageFreezeMapper freezeMapper;
// ========== Try 阶段:冻结库存 ==========
@Override
@Transactional // 必须写在实现类!!!
public boolean tryDeduct(String productId, Integer count) {
// 1. 检查库存
Storage storage = storageMapper.selectByProductId(productId);
if (storage.getStock() < count) throw new RuntimeException("库存不足");
// 2. 插入冻结记录 (状态: TRY)
StorageFreeze freeze = new StorageFreeze();
freeze.setXid(RootContext.getXID());
freeze.setState(StorageFreeze.State.TRY);
freezeMapper.insert(freeze);
// 3. 扣减可用库存
storage.setStock(storage.getStock() - count);
storageMapper.updateById(storage);
return true;
}
// ========== Confirm 阶段:确认扣减 ==========
@Override
public boolean confirm(BusinessActionContext context) {
String xid = context.getXid();
// 幂等:更新冻结状态为 CONFIRM
StorageFreeze freeze = freezeMapper.selectById(xid);
freeze.setState(StorageFreeze.State.CONFIRM);
freezeMapper.updateById(freeze);
return true;
}
// ========== Cancel 阶段:取消回滚 ==========
@Override
public boolean cancel(BusinessActionContext context) {
String xid = context.getXid();
StorageFreeze freeze = freezeMapper.selectById(xid);
// 1. 空回滚/防悬挂
if (freeze == null || freeze.getState() != StorageFreeze.State.TRY) return true;
// 2. 恢复库存
Storage storage = storageMapper.selectByProductId(freeze.getProductId());
storage.setStock(storage.getStock() + freeze.getFreezeCount());
storageMapper.updateById(storage);
// 3. 更新状态为 CANCEL
freeze.setState(StorageFreeze.State.CANCEL);
freezeMapper.updateById(freeze);
return true;
}
}
3. 优缺点
- 优点
- ✅ 性能巅峰:无数据库锁,完全异步化,高并发首选。
- ✅ 跨数据源:支持 NoSQL、Redis、HTTP 等非关系型存储。
- ✅ 灵活可控:业务自定义隔离与回滚逻辑。
- 缺点
- ❌ 高侵入性:需开发 Try/Confirm/Cancel 三个方法,代码量大。
- ❌ 复杂度高:必须处理幂等、空回滚、防悬挂三大问题。
- ❌ 开发量大:每个参与者都需改造为 TCC 接口。
4. 适用场景
高并发、高性能场景(如秒杀、红包);需操作非关系型数据库(Redis、MongoDB)的场景。
五、Saga 模式:长事务与复杂流程补偿
1. 核心原理
Saga 是针对长事务、多服务、跨异步场景的最终一致性方案。将全局事务拆分为多个本地短事务,每个事务对应一个正向服务和一个补偿服务。
- 正向执行:按顺序执行 A→B→C→D 所有正向服务。
- 反向补偿:若 C 失败,逆序执行 C 的补偿→B 的补偿→A 的补偿,最终恢复一致。
Seata 提供两种实现:
- 注解式 (@SagaTransactional):简单编排,适合线性流程。
- 状态机 (JSON 定义):复杂编排,支持异步、选择、重试、回退。
2. 优缺点
- 优点
- ✅ 长事务支持:支持分钟 / 小时级事务(如跨境支付、供应链)。
- ✅ 无锁高性能:本地事务一阶段提交,无阻塞。
- ✅ 跨系统兼容:可集成遗留系统、第三方服务。
- 缺点
- ❌ 最终一致性:存在中间状态,隔离性差。
- ❌ 补偿复杂:需编写所有服务的补偿逻辑,设计难度大。
- ❌ 数据可见:失败前的中间数据已对外可见。
3. 适用场景
业务流程长、参与者多、跨系统 / 异步(如电商大促订单、金融信贷审批、物流调度)。
六、四大模式核心对比(选型指南)
| 特性维度 | XA 模式 | AT 模式 | TCC 模式 | Saga 模式 |
|---|---|---|---|---|
| 一致性 | 强一致 (ACID) | 最终一致 | 最终一致 | 最终一致 |
| 侵入性 | 零侵入 | 零侵入 | 高侵入 (3 接口) | 中侵入 (补偿) |
| 性能 | 最差 (长锁) | 中 (自动) | 最优 (无锁) | 高 (异步) |
| 隔离性 | 读已提交 | 读未提交 | 业务自定义 | 无隔离 |
| 数据库依赖 | XA 协议 | RDBMS | 无 (支持 NoSQL) | 无 (任意存储) |
| 复杂度 | 低 | 低 | 极高 | 高 |
| 适用场景 | 金融核心 | 通用微服务 | 高并发 / 非 DB | 长事务 / 复杂流程 |
七、SpringBoot 客户端核心注意事项(生产避坑大全)
1. 事务分组必须全局一致
所有微服务的 tx-service-group 与 TC 端 vgroup-mapping 保持一致,否则无法发现事务服务。
2. 数据源代理严格区分模式
- AT/XA 必须开启数据源代理;
- TCC 可以和AT一起用
3. TCC 模式三大铁律(极易踩坑)
- 必须拆分为接口 + 实现类,不可以一个类写完;
@LocalTCC必须写在接口上;@Transactional必须写在实现类 Try 方法上,不可写在接口。
结论:TCC 结构不分离 → 只执行 Try,不执行 Confirm/Cancel。
4. AT 模式异常绝对不能吞吃
AT 模式依靠异常抛出来触发回滚。如果 RM 分支服务内部 try-catch 吃掉异常,不继续抛出,Seata 与 TM 完全感知不到失败,会判定分支执行成功,全局直接提交,导致数据错乱。
- 异常抛出 → 分支失败 → 全局回滚;
- 异常被吞 → 分支上报成功 → 全局提交不回滚。
结论:AT 吞异常 → 事务不回滚,数据必乱。
5. 最终金规:TCC 看结构,AT 看异常
- TCC 不分离 → 二阶段不执行
- AT 吞异常 → 事务不回滚
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)