SEATA AT vs SAGA vs 本地消息表
AT模式
是一种无侵入的解决方案,基于SQL解析自动生成回滚日志。它的优点是对业务代码侵入小,只需要添加@GlobalTransactional注解即可。适合短事务场景(1秒左右内处理完事务),比如订单支付、库存扣减等。但缺点是仅支持关系型数据库,在长事务场景下会有全局锁竞争问题。
SEATA 的 AT 模式(Automatic Transaction) 是一种基于改进的两阶段提交(2PC)协议的无侵入分布式事务解决方案,通过自动生成数据快照和回滚日志,实现分布式事务的最终一致性。以下是其核心原理及阶段划分:
一、AT 模式核心原理
- 无侵入设计
业务代码无需改造,仅需通过@GlobalTransactional注解标记全局事务边界。 - 两阶段提交优化
与传统 XA 模式不同,AT 模式在一阶段直接提交本地事务,释放数据库资源,通过全局锁和 undo_log 表保障隔离性和可回滚性。 - 关键组件
- TC(事务协调器):独立部署,管理全局事务状态和分支协调。
- TM(事务管理器):定义全局事务边界(如注解触发)。
- RM(资源管理器):拦截 SQL、生成回滚日志,并与 TC 通信。
二、一阶段:本地事务提交与准备
目标:执行业务 SQL,记录数据快照,注册分支事务。
流程:
- SQL 解析与拦截
RM 通过数据源代理拦截业务 SQL,解析类型(INSERT/UPDATE/DELETE)、表名、条件等。 - 生成前镜像(Before Image)
执行 SQL 前,查询并保存修改前的数据快照(例如SELECT * FROM table WHERE id=1)。 - 执行业务 SQL
提交 SQL 操作(如UPDATE table SET stock=90 WHERE id=1)。 - 生成后镜像(After Image)
执行 SQL 后,再次查询数据,保存修改后的状态。 - 记录回滚日志(undo_log)
将前后镜像组成 JSON 格式的undo_log,插入业务数据库的undo_log表中。 - 注册分支事务与全局锁
- 向 TC 注册分支事务,申请目标数据的全局锁(例如锁定
id=1的记录)。 - 在同一个本地事务中提交业务数据和
undo_log,释放本地数据库锁(非全局锁)。
- 向 TC 注册分支事务,申请目标数据的全局锁(例如锁定
✅ 关键点:一阶段已完成本地事务提交,释放连接资源,性能较高;全局锁防止其他事务修改同一数据。
三、二阶段:全局提交或回滚
目标:根据 TC 的决策,异步清理或回滚数据。
流程:
- TC 决策
TM 通知 TC 全局事务结束,TC 检查所有分支事务状态。 - 全局提交(所有分支成功)
- TC 通知各分支异步删除
undo_log记录。 - 无需数据操作(因一阶段已提交),仅清理日志,效率极高。
- TC 通知各分支异步删除
- 全局回滚(任一分支失败)
- TC 通知成功分支根据
undo_log回滚。 - 回滚步骤:
- 校验脏写:比较当前数据与后镜像是否一致。若不一致,说明数据被其他事务修改,需人工介入。
- 生成反向 SQL:根据前镜像生成逆向操作(如将
stock=90回滚为stock=100)。 - 执行回滚:在本地事务中执行反向 SQL,并删除
undo_log。
- TC 通知成功分支根据
⚠️ 脏写校验:回滚前校验数据一致性,避免覆盖其他事务的修改。
四、关键机制与注意事项
- 隔离性保障
- 写隔离:通过全局锁(
SELECT FOR UPDATE)确保同一记录仅一个全局事务可修改。 - 读隔离:默认读未提交(Read Uncommitted),可通过
SELECT FOR UPDATE升级为读已提交(Read Committed)。
- 写隔离:通过全局锁(
- 性能优化
- 一阶段提交释放本地资源,二阶段异步清理,减少锁竞争。
- 避免长事务,防止全局锁长时间占用。
- 适用场景
- 适合:Java 技术栈、短事务(如订单创建、库存扣减)。
- 不适合:跨语言微服务、非关系型数据库、金融级强一致性场景(需 TCC 模式)。
SAGA模式
是为长事务(数秒)设计的解决方案,通过正向操作和补偿操作来实现最终一致性。它的优点是没有全局锁,适合跨多个服务的业务流程,参与者可以异步执行。但缺点是需要手动实现补偿逻辑,状态管理复杂。
由于 Saga 事务不保证隔离性, 在极端情况下可能由于脏写无法完成回滚操作, 比如举一个极端的例子, 分布式事务内先给用户A充值, 然后给用户B扣减余额, 如果在给A用户充值成功, 在事务提交以前, A用户把余额消费掉了, 如果事务发生回滚, 这时则没有办法进行补偿了。这就是缺乏隔离性造成的典型的问题, 实践中一般的应对方法是:
业务流程设计时遵循“宁可长款, 不可短款”的原则, 长款意思是客户少了钱机构多了钱, 以机构信誉可以给客户退款, 反之则是短款, 少的钱可能追不回来了。所以在业务流程设计上一定是先扣款。
有些业务场景可以允许让业务最终成功, 在回滚不了的情况下可以继续重试完成后面的流程, 所以状态机引擎除了提供“回滚”能力还需要提供“向前”恢复上下文继续执行的能力, 让业务最终执行成功, 达到最终一致性的目的。
在 Seata 分布式事务框架中,SAGA 模式和 AT 模式是两种主流解决方案,但其设计目标和适用场景存在显著差异。以下是结合核心原理、适用性及实践建议的选型指南:
Saga的其他替代方案:本地消息表
⚙️ 一、核心机制对比
| 维度 | AT 模式 | SAGA 模式 |
|---|---|---|
| 一致性级别 | 最终一致(默认) | 最终一致 |
| 事务锁机制 | 依赖全局锁(高并发下可能阻塞) | 无全局锁(异步执行,无阻塞) |
| 业务侵入性 | 无侵入(仅需注解) | 需手动实现补偿逻辑 |
| 事务时长支持 | 短事务(秒级) | 长事务(分钟/小时级) |
| 隔离性 | 弱隔离(需 @GlobalLock 防脏读) |
无隔离(可能脏读) |
🎯 二、适用场景决策
优先选择 AT 模式 ✅
- 简单跨服务事务
- 例如:订单创建(操作订单表)→ 库存扣减(操作库存表),事务链路短且逻辑简单。
- 优势:无需额外编码,通过
@GlobalTransactional自动管理回滚。
- 强依赖关系型数据库
- 仅支持 MySQL/Oracle 等 ACID 数据库,无法接入 Redis/MongoDB 等 NoSQL。
- 对开发效率要求高
- 快速上线场景,避免补偿逻辑开发成本。
优先选择 SAGA 模式 ✅
- 长流程业务
- 例如:电商下单(订单→支付→物流→通知),涉及多服务且执行时间长(>30秒)。
- 优势:无锁设计避免资源长期占用,支持异步执行。
- 跨异构系统集成
- 需调用外部服务(如第三方支付、海关清关),无法改造其接口实现 TCC 时。
- 高并发且容忍最终一致
- 如秒杀活动中库存扣减与订单创建的分离,通过补偿保证最终一致。
⚠️ 三、关键缺陷与规避方案
| 模式 | 典型问题 | 解决方案 |
|---|---|---|
| AT 模式 | 高并发下全局锁竞争 | 分库分表降低锁粒度;设置合理超时时间 |
| 复杂 SQL 解析失败(如子查询) | 手动编写补偿 SQL 或改用 TCC | |
| SAGA 模式 | 补偿逻辑实现复杂 | 用状态机引擎(如 Seata StateMachine)标准化流程 |
| 补偿失败导致数据不一致 | 增加重试机制 + 人工兜底干预 |
💡 五、实践建议
- 混合模式使用
复杂系统中可组合模式(如核心支付用 TCC,物流通知用 SAGA)。 - SAGA 补偿设计原则
- 补偿操作需幂等(通过业务 ID 去重)。
- 正向操作与补偿操作成对设计(如
createOrder→cancelOrder)。
- 监控与治理
- AT 模式监控全局锁竞争率;SAGA 模式跟踪事务状态机执行链路。
💎 总结
- 选 AT:短事务、简单逻辑、追求开发效率、强依赖关系型数据库。
- 选 SAGA:长事务、跨异构系统、高并发无锁需求、业务容忍最终一致。
实际选型需结合事务时长、一致性要求及团队技术储备综合判断,必要时可混合模式灵活应对。

浙公网安备 33010602011771号