关于分布式事务框架
常用分布式事务框架及其实现原理
分布式事务是微服务架构中的核心难题,主流框架基本围绕 CAP 定理 和 BASE 理论 来做trade-off。
一、分布式事务理论基础
| 理论 | 核心思想 |
|---|---|
| 2PC(两阶段提交) | 协调者先询问所有参与者能否提交(Prepare),全部OK再真正提交(Commit) |
| TCC(Try-Confirm-Cancel) | 业务层面的两阶段提交,Try预留资源,Confirm确认,Cancel回滚 |
| SAGA | 将长事务拆成多个本地事务,每个本地事务有对应的补偿操作,正向执行失败则反向补偿 |
| 本地消息表 | 将消息与业务数据在同一事务中写入本地表,异步投递消息保证最终一致性 |
| 事务消息 | 利用MQ的半消息机制,确保本地事务与消息发送的原子性 |
二、主流框架详解
1. Seata(阿里)
GitHub Star 最多的分布式事务框架,支持四种事务模式:
1.1 AT 模式(自动补偿,最常用)
原理:对业务无侵入,基于 两阶段提交 + 全局锁 实现。
第一阶段(分支事务执行):
1. 拦截 SQL,解析语义
2. 查询修改前数据,生成 before-image(前镜像)
3. 执行业务 SQL
4. 查询修改后数据,生成 after-image(后镜像)
5. 生成 undo_log 并与业务 SQL 在同一个本地事务中提交
6. 向 TC 注册分支事务,申请该行数据的全局锁
第二阶段(全局提交/回滚):
- 提交:异步清理 undo_log(因为一阶段已提交)
- 回滚:根据 undo_log 的 before-image 反向补偿,同时校验 after-image 防脏写
关键设计:
- 全局锁:一阶段本地事务提交后,会持有全局锁直到全局事务结束,防止脏写
- 写隔离:全局事务在本地事务提交前获取全局锁,拿不到则重试或回滚
- 读隔离:默认不加全局锁(读未提交),可配置
SELECT FOR UPDATE实现读已提交
适用场景:一般的 CRUD 业务,对业务代码无侵入(仅加 @GlobalTransactional 注解)
1.2 TCC 模式
原理:业务层面的两阶段提交,需要手动编写 Try/Confirm/Cancel 三个方法。
Try:预留资源(如冻结库存、冻结金额)
Confirm:确认执行(如扣减冻结库存、扣减冻结金额)
Cancel:取消执行(如释放冻结库存、释放冻结金额)
关键设计:
- 空回滚:Try 未执行但收到了 Cancel 请求,需要在 Cancel 中判断并直接返回成功
- 幂等控制:Confirm/Cancel 可能被重复调用,必须保证幂等
- 悬挂:Cancel 先于 Try 到达,需要阻止 Try 执行(通过记录 Cancel 已执行的状态)
适用场景:非关系型数据库、性能要求高、需要精细控制资源预留的场景
1.3 SAGA 模式
原理:长事务解决方案,每个参与者只需提供正向和反向补偿两个动作。
正向执行:T1 → T2 → T3 → ... → Tn
反向补偿:Tn失败 → C3 → C2 → C1
关键设计:
- 向前恢复:重试失败步骤(适合必须成功的场景)
- 向后恢复:补偿已完成的步骤(适合可接受失败的场景)
- 缺乏隔离性:SAGA 模式没有全局锁,可能存在脏写,需要业务层面处理
适用场景:业务流程长、参与者多、对性能要求高、允许最终一致性的场景
1.4 XA 模式
原理:基于数据库的 XA 协议实现两阶段提交,Seata 做了代理优化。
第一阶段:所有参与者执行 SQL 但不提交(XA PREPARE)
第二阶段:TC 通知所有参与者提交或回滚(XA COMMIT/ROLLBACK)
关键设计:
- 数据库层面保证一致性,隔离性好
- 但全局锁持有时间长,性能较差
- Seata 的 XA 模式通过代理数据源,对业务无侵入
适用场景:对一致性要求极高,可接受性能损失的场景
2. Hmily(金融级TCC)
百度开源的 TCC 分布式事务框架,后由作者独立维护。
实现原理:
核心架构:
1. Try 阶段:执行业务方法,记录事务日志
2. Confirm/Cancel 阶段:根据事务日志异步调度执行
3. 事务恢复:定时任务扫描未完成事务进行重试
关键特性:
- 异步 Confirm/Cancel:Try 成功后立即返回,Confirm/Cancel 由框架异步执行
- 事务日志:记录在本地数据库(MySQL/MongoDB/Redis 等)
- 支持嵌套事务
- 支持事务上下文传递(RPC 隐式传参)
适用场景:金融业务,对 TCC 模式有深度需求的场景
3. EasyTransaction(易物联)
一个综合性的分布式事务框架,同时支持多种模式。
实现原理:
- TCC:与 Hmily 类似
- 补偿:SAGA 风格的补偿模式
- 可靠消息:本地消息表模式
- 框架会根据调用链路自动选择最优模式
适用场景:需要灵活组合多种事务模式的复杂业务
4. Myth(可靠消息最终一致性)
专注于 本地消息表 模式的分布式事务框架。
实现原理:
1. 业务操作与消息记录在同一本地事务中提交
2. 后台线程定时扫描消息表,将未发送的消息投递到 MQ
3. 消费者消费消息并执行本地事务
4. 消费成功后发送确认,框架删除或标记消息已处理
5. 超时未确认的消息会重复投递,消费者需保证幂等
适用场景:异步场景、对实时性要求不高、追求最终一致性
5. RocketMQ 事务消息
RocketMQ 自身提供的分布式事务能力,4.3.0+ 版本支持。
实现原理:
1. 生产者发送半消息(Half Message)到 Broker
→ 半消息对消费者不可见
2. Broker 返回发送成功,生产者执行本地事务
3. 根据本地事务结果,发送 Commit 或 Rollback 给 Broker
→ Commit:半消息变为可消费消息
→ Rollback:半消息被删除
4. 如果 Broker 长时间未收到二次确认(网络闪断等):
→ 启动回查机制,检查本地事务状态
→ 根据回查结果决定 Commit 或 Rollback
5. 消费者消费消息,执行远程事务
→ 消费失败会重试,消费者需保证幂等
适用场景:异步解耦场景、与 RocketMQ 生态紧密集成的系统
6. XA 协议(数据库原生方案)
所有支持 XA 协议的数据库自带的分布式事务能力。
实现原理:
全局事务管理器(TM)协调:
1. TM 通知所有 RM(资源管理器)开启 XA 事务
2. 各 RM 执行 SQL,但不提交(XA PREPARE)
3. 所有 RM Prepare 成功后,TM 发送 XA COMMIT
4. 任一 RM Prepare 失败,TM 发送 XA ROLLBACK
局限:
- 全局锁持有时间长,吞吐量低
- 对数据库有强依赖
- 单点故障风险(TM)
- 有 XA 2PC 的固有问题:协调者宕机可能导致参与者长时间阻塞
适用场景:传统数据库架构、强一致性需求、可接受性能损失
三、框架对比总结
| 框架 | 支持模式 | 侵入性 | 性能 | 一致性 | 维护状态 |
|---|---|---|---|---|---|
| Seata | AT/TCC/SAGA/XA | AT低/TCC高 | AT较好 | AT强一致 | 活跃(阿里) |
| Hmily | TCC | 高 | 高 | 强一致 | 社区维护 |
| EasyTransaction | TCC/补偿/可靠消息 | 中 | 较好 | 最终一致 | 社区维护 |
| Myth | 本地消息表 | 低 | 高 | 最终一致 | 社区维护 |
| RocketMQ | 事务消息 | 低 | 高 | 最终一致 | 活跃(阿里) |
| XA 协议 | 两阶段提交 | 低 | 低 | 强一致 | 数据库原生 |
四、如何选型
1. 强一致性 + 低侵入 → Seata AT 模式(最推荐)
2. 强一致性 + 高性能 → Seata TCC 模式 / Hmily
3. 最终一致性 + 异步解耦 → RocketMQ 事务消息
4. 长流程 + 最终一致性 → Seata SAGA 模式
5. 传统架构 + 强一致性 → XA 协议
6. 综合场景 → Seata(多种模式可混用)
实际生产环境中,Seata 是目前使用最广泛的方案,其 AT 模式对业务侵入最小、接入最简单,而 TCC/SAGA 可覆盖更复杂的场景。RocketMQ 事务消息则在异步场景中表现出色。

浙公网安备 33010602011771号