分布式事务实战:跨服务一致性,四种方案怎么选

举报
yd_237615889 发表于 2026/09/21 09:15:50 2026/09/21
【摘要】 博客 · 系统设计 / 分布式 · 2026-09-21分布式事务实战:跨服务一致性,四种方案怎么选拆成微服务之后,"下单成功但库存没扣"成了经典事故。这篇讲清 2PC、TCC、Saga、消息表四种方案的机制与代价、怎么选,以及绕不开的三个工程细节:幂等、状态机、对账。工程实践手记 ·2026-09-21 ·约 13 分钟阅读一、先立地基:三个概念单体时代,一致性靠数据库本地事务:BEGIN...
博客 · 系统设计 / 分布式 · 2026-09-21

分布式事务实战:跨服务一致性,四种方案怎么选

拆成微服务之后,"下单成功但库存没扣"成了经典事故。这篇讲清 2PC、TCC、Saga、消息表四种方案的机制与代价、怎么选,以及绕不开的三个工程细节:幂等、状态机、对账。


工程实践手记 ·2026-09-21 ·约 13 分钟阅读

一、先立地基:三个概念

单体时代,一致性靠数据库本地事务:BEGIN、COMMIT、ROLLBACK,ACID 四平八稳。拆成微服务之后,一次下单要动订单库、库存库、账户库——分属三个服务、三个数据库,本地事务管不了跨库操作。

  • CAP 的直觉版:网络分区不可避免,于是「强一致」与「高可用」只能二选一——所有分布式事务方案,都是在这两极之间找位置
  • BASE 与最终一致:绝大多数业务接受「短暂不一致、最终一致」——这是 Saga 与消息表的立足点
  • 补偿不是回滚:分布式下没有数据库级回滚,只有反向操作(把扣掉的库存加回去);反向操作可能失败、可能重复——这引出了后面所有工程细节
分布式事务的本质,是用「补偿 + 幂等 + 对账」去逼近一致,而不是真的拥有回滚。
· · ·

二、四种方案:机制与代价

方案 一致性 侵入性 性能 典型场景
2PC / XA 强一致 低(框架层) 差(同步阻塞) 强一致、低频、小规模
TCC 强一致(业务层) 高(三接口) 好 资金、库存等核心链路
Saga 最终一致 中 好 长流程、可补偿业务
本地消息表 / 事务消息 最终一致 低 好 事件驱动、已用 MQ

2PC:准备与提交两步走

协调者先让所有参与方「准备」(锁住资源、写好日志),全部就绪后再统一「提交」;任何一方准备失败就统一回滚。优点是业务无侵入;代价是同步阻塞——事务期间资源被锁住,参与者一慢全体等;协调者本身还有单点风险。它适合「强一致 + 低频 + 参与方少」,不适合高并发主链路。

TCC:把事务拆成三段业务代码

Try(预留资源)→ Confirm(确认扣减)→ Cancel(释放预留)。以扣库存为例:Try 阶段把 10 件「冻结」而不是扣减,Confirm 时真正扣掉,Cancel 时解冻。性能好、一致性强,代价是侵入性高——每个参与方都要实现三个接口,且要处理三个经典坑:空回滚(Cancel 先于 Try 到达,必须识别并直接成功)、幂等(Confirm 与 Cancel 可能被重复调用,用事务 ID 去重)、防悬挂(空回滚后迟到的 Try 不能再生效)。

Try     : 冻结资源(frozen = 10)
Confirm : 扣减(stock -= frozen)并清除冻结
Cancel  : 解冻(frozen = 0),若未曾 Try 则直接成功

Saga:长流程的补偿链

把一个大事务拆成一串本地事务:T1、T2、T3 依次执行;一旦 T3 失败,就按逆序执行补偿 C2、C1。它没有「预留」概念,靠补偿兜底,因此适合跨多个服务的长流程(旅行预订:机票、酒店、租车)。两种实现风格:编排式(中心协调者决定下一步,好理解、好排障)与协同式(各服务监听事件自行反应,耦合低但链路难追踪)。新手建议从编排式起步。

本地消息表与事务消息

业务写入与「待发消息」放进同一个本地事务,再由异步投递器可靠送到 MQ,下游各自消费。它的关键是:不追求同步一致,而是保证「业务成功则消息必然发出」,配合下游幂等与 T+1 对账,最终收敛。

· · ·

三、选型:能不用就不用

选型的第一个问题不是「选哪个」,而是「这个链路真的需要分布式事务吗」——很多所谓的跨服务一致性问题,可以通过重新设计边界(把强一致的数据放回一个库)直接消除。真的需要时:资金、库存等核心链路要求强一致且并发可控 → TCC;长流程、每步都有天然反向操作 → Saga;事件驱动、已经用了 MQ → 本地消息表 / 事务消息;存量系统、参与方都支持 XA 且频率极低 → 2PC 兜底;非核心链路(通知、积分)→ 干脆别上,接受最终一致 + 对账。

一条经验:越靠近钱的链路越用强一致方案,越靠近「体验」的链路越用最终一致。

四、绕不开的三个工程细节

  • 幂等:所有 Confirm / Cancel / 补偿接口必须幂等——没有幂等,重试就会变成重复扣款,这是头号事故源
  • 状态机与去重表:记录每个事务走到哪一步,用事务 ID 做唯一键;空回滚、防悬挂、重复调用全靠它兜住
  • 对账:T+1 比对上下游数据、发现差异并修复——没有对账的最终一致,等于最终不一致

五、五个常见误区

  • 用 2PC 扛大流量:同步阻塞与锁等待会把系统拖垮——它天生不适合高并发
  • 只测成功路径:TCC 与 Saga 的价值恰恰在失败与补偿路径,必须专门写测试
  • 把补偿当回滚:补偿是有副作用的业务操作,可能部分失败或重复执行
  • 忽略对账:把一致性完全托付给中间件,出事时没有兜底手段
  • 过度设计:给积分、通知这类链路套上 TCC,用复杂度换来了不需要的「安全感」

六、落地路线:四步走

  • 分类:盘点所有跨服务写操作,标注需要强一致还是最终一致——多数可以在重设计中降级
  • 起步:非核心链路统一走消息表 / 事件驱动;长流程用编排式 Saga
  • 补基础件:幂等组件、事务状态机、对账任务——三件套是所有方案的公共底座
  • 评估 TCC:只对资金与库存等真正敏感的链路引入,并把空回滚、防悬挂、幂等全部纳入测试

速查卡

场景 方案
强一致、低频、参与方少 2PC / XA
资金、库存,要求强一致 TCC(三接口 + 幂等 + 防悬挂)
长流程、每步可反向操作 Saga(编排式起步)
事件驱动、已用 MQ 本地消息表 / 事务消息
通知、积分等非核心 最终一致 + 对账
公共底座 幂等去重表 + 事务状态机 + T+1 对账

写在最后

分布式事务没有银弹,只有权衡:越强的一致,越贵的代价。正确的姿势是先问「这个链路能不能不要分布式事务」,再在剩下的场景里按「钱 vs 体验」分配方案,最后老老实实补上幂等、状态机、对账这三件公共底座。

下一步 · 盘点真正需要强一致的链路
把系统里所有跨服务写操作列成一张表,逐条标注「强一致 / 最终一致」——你会发现需要 TCC 的场景通常不到两成。系列下一篇候选:语义化版本自动发版、前端性能优化、对话系统评测。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。