Skip to content

分布式事务常见解决方案总览

凌晨 3 点,你的报警平台突然炸了——订单服务说库存服务没扣库存,库存服务说订单服务没发请求,财务系统一脸懵逼:「钱扣了,货呢?」

这不是 bug,这是分布式事务的经典困境:跨服务的数据一致性

为什么分布式事务是分布式系统最大的难题之一?因为它直接撞上了 CAP 理论 的天花板—— Consistency(一致性)、Availability(可用性)、Partition tolerance(分区容错性),三者只能选其二,而网络分区是必然发生的。

换句话说:在分布式系统中,要么接受数据不一致,要么接受系统不可用。分布式事务的种种方案,本质上都是在这两者之间寻找平衡点。

从强一致到最终一致:一条艰难的路

分布式事务解决方案可以分为两大阵营:

强一致性方案:不惜一切代价保证数据完全一致

最终一致性方案:允许短暂的不一致,但保证最终一致

方案一致性级别性能开发成本适用场景
2PC/3PC强一致对数据一致性要求极高的场景
Seata AT强一致业务代码无侵入,支持单库多表
Seata TCC最终一致高性能,强一致性,业务可改写
Saga最终一致长事务,流程编排
可靠消息最终一致异步解耦,允许短暂不一致
最大努力通知最终一致通知类场景,允许失败重试

没有银弹,每种方案都是一致性、成本、性能的权衡。选错方案,轻则系统卡顿,重则数据错乱。

强一致性方案:2PC 与 3PC

2PC(Two-Phase Commit)

2PC 是最经典的分布式事务协议,由协调者(Coordinator)和参与者(Participant)组成:

一阶段(投票阶段)

  • 协调者向所有参与者发送「准备好」请求
  • 参与者执行事务,但不提交
  • 参与者返回「同意」或「反对」

二阶段(提交阶段)

  • 如果所有参与者都返回「同意」,协调者发送「提交」指令
  • 如果任何一个参与者返回「反对」,协调者发送「回滚」指令

2PC 的致命缺陷

  • 同步阻塞:参与者收到「准备好」后,必须阻塞等待,直到收到提交或回滚
  • 单点故障:协调者挂了,参与者就死等了
  • 数据不一致:协调者发送「提交」后挂了,只有部分参与者收到提交,导致数据不一致

3PC(Three-Phase Commit)

3PC 是 2PC 的改良版,把提交分成三个阶段:

  • CanCommit:协调者问参与者「你们能提交吗」
  • PreCommit:协调者告诉参与者「准备提交」,超时自动中断
  • DoCommit:真正提交

3PC 解决了同步阻塞和单点故障的部分问题(超时机制),但数据不一致问题依然存在

强一致性方案的共同问题:性能太差。全局锁、多次网络通信、参与者必须等待——这套机制在互联网高并发场景下几乎不可用。

最终一致性方案:百花齐放

强一致性方案性能太差,所以最终一致性方案应运而生。

核心思想:放弃实时一致,接受短暂不一致,用补偿机制保证最终一致。

TCC(Try-Confirm-Cancel)

Seata TCC 模式 把每个分布式事务分成三步:

  1. Try:预留资源,但不提交
  2. Confirm:确认执行,使用预留的资源
  3. Cancel:取消执行,释放预留的资源

关键点:Try/Confirm/Cancel 都需要业务方自己实现。TCC 是业务层面的补偿,需要在代码里写好预留、确认、取消的逻辑。

Saga

Seata Saga 模式 适合长事务编排。把一个大事务拆成多个小事务,每个小事务都有对应的补偿操作。正向执行,出错就反向补偿。

TCC vs Saga

  • TCC 是「先锁定再执行」,资源在 Try 阶段就被预留了
  • Saga 是「直接执行,出事再补偿」,不锁定资源

可靠消息

可靠消息最终一致性方案 的核心是消息队列。本地事务执行成功后,消息一定被投递到下游。

两种实现方式:

  • 本地消息表:本地事务 + 消息表,用定时任务轮询投递
  • RocketMQ 事务消息:半消息(Half Message)机制,反查本地事务状态

最大努力通知

最大努力通知方案 是「可靠消息」的镜像——可靠消息保证发送方,最大努力通知保证接收方

典型场景:支付回调、订单状态同步。核心机制是重复通知 + 指数退避 + 衰减通知次数

选型决策树:怎么快速选择?

需要强一致性?
├── 是 → 业务代码能改吗?
│   ├── 能 → TCC(高性能)或 AT(零侵入)
│   └── 不能 → AT 模式(如果有框架支持)
└── 否 → 是异步解耦还是长事务?
    ├── 异步解耦 → 可靠消息(MQ 事务消息)
    └── 长事务 → Saga 编排

更详细的选型分析:AT vs TCC vs SAGA 对比与选型

面试追问方向

  1. CAP 理论在分布式事务中怎么体现?

    • 强一致性方案选择了 C+P,意味着可能牺牲可用性
    • 最终一致性方案选择了 A+P,在网络分区时保证可用,允许短暂不一致
  2. 2PC 的数据不一致问题怎么解决?

    • 加协调者选举 Zab/Raft 协议
    • 或者干脆不用 2PC,用最终一致性方案
  3. 如果让你设计一个分布式事务框架,核心模块有哪些?

    • 事务协调器:管理全局事务状态
    • 分支事务注册:让参与者加入全局事务
    • 补偿/回滚机制:处理失败情况
    • 隔离性保证:全局锁或资源预留
  4. 本地消息表和 RocketMQ 事务消息的区别?

    • 本地消息表:业务自己实现,需要轮询任务
    • RocketMQ 事务消息:MQ 原生支持,反查机制更可靠

没有银弹

分布式事务的难点不在于找到「完美方案」,而在于理解每种方案的权衡,根据业务场景做出合理选择。

是追求强一致还是最终一致?业务代码能改吗?性能要求有多高?能接受多长时间的窗口期?

这些问题没有标准答案,只有最适合当前业务的答案。

下次遇到分布式事务问题,别急着找框架,先问自己:这笔交易能承受多长时间的「不一致」?

基于 VitePress 构建