分布式事务问题的 7 种常见解决方案 - 苏三说技术
前言
分布式事务问题,无论在面试,还是工作中经常会遇到。
分布式系统下,数据一致性不再是数据库事务那么简单的。
分布式事务作为其中最复杂的挑战之一,曾让无数团队深夜加班、焦头烂额。
今天这篇文章就跟大家一起聊聊分布式事务问题的 7 种常见解决方案,希望对你会有所帮助。
1.为什么分布式事务如此棘手?
在单体应用时代,数据库的 ACID 事务保证了数据一致性。
但在微服务架构下,一个业务操作需要跨多个服务、多个数据库,传统事务模型不再适用。
想象一下电商下单场景:
- 订单服务创建订单(订单数据库)
- 库存服务扣减库存(库存数据库)
- 支付服务处理支付(支付数据库)
- 积分服务增加积分(积分数据库) 这四个操作要么全部成功,要么全部失败。
这就是分布式事务要解决的核心问题。
那么,如何解决问题呢?
2. 常见的解决方案
2.1 2PC(两阶段提交)
该方案是强一致性方案。
2PC 是最经典的分布式事务协议,通过协调者(Coordinator)统一调度参与者(Participant)的执行。
分为两个阶段:\n
第一阶段:准备阶段\n 协调者询问所有参与者:“能否提交事务?”
参与者执行本地事务但不提交,锁定资源并回复 YES/NO。
第二阶段:提交/回滚阶段
-
若所有参与者返回 YES,协调者发送 commit 命令,参与者提交事务
-
若有任一参与者返回 NO,协调者发送 rollback 命令,参与者回滚事务 致命缺陷:
-
同步阻塞:所有参与者在 prepare 后锁定资源,直到收到 commit/rollback(高并发下吞吐量骤降)
-
单点故障:协调者宕机导致参与者永久阻塞
-
数据不一致:网络分区时部分参与者可能提交成功
2.2 3PC(三阶段提交)
该方案也是强一致性方案。
3PC 可以解决 2PC 阻塞问题。
3PC 在 2PC 基础上增加预提交阶段,并引入超时机制:
- CanCommit 阶段:协调者询问参与者状态(不锁定资源)
- PreCommit 阶段:参与者锁定资源并执行 SQL(不提交)
- DoCommit 阶段:正式提交 改进点:
-
参与者超时未收到命令自动提交(降低阻塞风险)
-
预提交阶段发现异常可提前终止 但依然存在问题:
-
网络分区时仍可能数据不一致
-
实现复杂度显著增加
2.3 TCC(Try-Confirm-Cancel)
该方案是最终一致性方案。
它是业务层面的 2PC。
TCC 将业务逻辑拆分为三个阶段:
- Try:预留资源(如冻结库存)
- Confirm:确认操作(正式扣减库存)
- Cancel:释放资源(解冻库存) 执行流程:
- 主业务调用所有服务的 try 方法
- 全部 try 成功则调用 confirm;任一 try 失败则调用 cancel 优势:
-
无全局锁:只在 try 阶段锁定局部资源
-
高可用:协调者可集群部署 挑战:
-
需手动实现回滚逻辑(业务侵入性强)
-
所有服务需提供三种接口 金融核心系统首选:某银行跨境支付系统采用 TCC 方案,日均处理 200 万笔交易,跨 5 个服务的事务成功率 99.99%
2.4 可靠消息最终一致性
该方案也是最终一致性方案。
可以使用 RocketMQ 的事务消息。
RocketMQ 的事务消息完美解决本地操作与消息发送的一致性问题:\n
关键步骤:
- 发送 half 消息(对消费者不可见)
- 执行本地事务
- 根据本地事务结果 commit/rollback
- MQ 定时回查未决事务 示例代码:
2.5 最大努力通知
该方案是弱一致性方案。
适用于对实时性要求低的场景(如短信通知):
- 业务主流程完成后发送通知
- 失败后按策略重试(如间隔 1min、5min、10min)
- 达到阈值后人工干预 实战经验:支付回调采用此方案,重试 8 次跨 12 小时,99.5% 的通知在 30 分钟内成功
2.6 Seata AT 模式
该方案是自动化的 TCC。
Seata 的 AT(Auto Transaction)模式在不侵入业务代码的前提下实现分布式事务:
核心机制:
- 全局锁:TC(事务协调器)管理内存级全局锁(替代数据库行锁)
- SQL 代理:解析业务 SQL 自动生成回滚日志
- 二阶段异步提交:极大提升吞吐量 性能对比:
局限:
- 不支持嵌套事务
- 热点数据更新冲突率高
2.7 eBay 事件队列
该方案是基于本地事务的最终一致性方案。
eBay 提出的经典方案:
- 将分布式操作拆分为本地事务 + 异步事件
- 使用事件表确保事件不丢失
- 通过补偿机制解决失败场景 该方案在早期 eBay 系统中每天处理 1 亿 + 事件,保证核心交易链路最终一致
3.方案的选型指南
根据业务场景选择合适方案:
黄金法则:
- 强一致性需求:选择 2PC/ZooKeeper(牺牲性能)
- 高并发场景:选择可靠消息/Seata AT(最终一致)
- 弱一致性场景:最大努力通知(成本最低)
总结
经过十年演进,分布式事务解决方案已从强一致性向高性能最终一致性发展。
技术没有绝对的好坏,只有适合与否。
我曾见过团队为了追求理论上的强一致性,把系统搞得复杂不堪;也见过过度追求性能导致资金损失的血泪教训。
分布式事务的本质,是在业务需求与技术可行性之间找到平衡点。
致开发者:不必追求完美的分布式事务解决方案,适合业务场景的才是最好的。
在设计时多问自己:
- 业务能容忍多长时间不一致?
- 事务失败后如何补偿?
- 是否有完善的监控和人工介入机制? 愿你在分布式系统的海洋中,乘风破浪,游刃有余。
最后说一句 (求关注,别白嫖我)
如果这篇文章对您有所帮助,或者有所启发的话,帮忙关注一下我的同名公众号:苏三说技术,您的支持是我坚持写作最大的动力。
求一键三连:点赞、转发、在看。
关注公众号:【苏三说技术】,在公众号中回复:进大厂,可以免费获取我最近整理的 10 万字的面试宝典,好多小伙伴靠这个宝典拿到了多家大厂的 offer。
本文收录于我的技术网站:http://www.susan.net.cn