分布式事物

发布于:2025-05-09 ⋅ 阅读:(10) ⋅ 点赞:(0)


一、2PC(Two-Phase Commit,两阶段提交)

✦ 背景动机:

最基础的分布式事务协议,由数据库起家(如 XA),核心在于协调者统一控制多个资源的提交与回滚

✦ 操作流程:

  1. 阶段一:Prepare(准备阶段)

    • 协调者向各参与者发送“准备提交事务”的请求。

    • 每个参与者执行事务操作,写入undo log(用于回滚),然后锁定相关资源(如数据库锁)。

    • 成功后回复“YES”,否则“NO”。

  2. 阶段二:Commit(提交阶段)

    • 如果协调者收到所有“YES”,发送“提交”指令;否则发送“回滚”指令。

    • 各参与者收到后执行提交或回滚操作。

✦ 优点:

  • 实现简单;

  • 一致性强(满足原子性:要么都提交,要么都回滚)。

✦ 缺点及问题:

  • 阻塞问题:参与者在Prepare后必须等待协调者,资源锁未释放,导致阻塞。

  • 单点故障问题:协调者如果崩溃,参与者无法得知提交或回滚结果,进入不确定状态

  • 无自动恢复机制:依赖协调者人工或脚本介入恢复。


二、3PC(Three-Phase Commit,三阶段提交)

✦ 背景动机:

为了解决2PC的阻塞和不确定性问题,3PC 在 2PC 的基础上引入了:

  • 中间状态(Pre-Commit)

  • 超时机制,避免永久阻塞;

  • 所有节点都可以基于状态做出决策

✦ 操作流程:

  1. Can Commit 阶段(询问提交)

    • 协调者发送“是否可以提交”;

    • 参与者判断能否执行,若可以则返回“Yes”;

    • 此阶段不做任何实际操作。

  2. Pre-Commit 阶段(预提交)

    • 如果都返回“Yes”,协调者发送“预提交”命令;

    • 参与者执行事务逻辑,但不提交,进入“可提交”状态,并记录日志;

    • 此时可以安全中断并重试。

  3. Do Commit 阶段(正式提交)

    • 协调者发送最终“提交”指令;

    • 若超时未收到协调者指令,参与者也可自主提交(因为已进入可提交状态)。

✦ 优点:

  • 避免阻塞:参与者等待超时可以自主提交或回滚;

  • 引入中间状态更易于恢复;

  • 状态明确:参与者通过自身状态判断可否提交。

✦ 缺点:

  • 实现复杂度更高;

  • 仍存在分布式网络不可靠带来的边缘问题(如脑裂);

  • 较少系统真正采用,更多用于教学和理论研究。


三、TCC(Try-Confirm-Cancel)

✦ 背景动机:

2PC/3PC适合数据库层面事务,但业务更复杂时,需要应用层控制事务。TCC就是基于这种“资源预留-确认-取消”的业务建模思想。

✦ 操作流程:

  1. Try:资源预留

    • 尝试执行事务,检查业务约束,预留资源(如冻结库存/余额),但不做实际变更。

  2. Confirm:确认提交

    • 如果 Try 阶段所有参与者都成功,调用 Confirm 执行实际操作(扣库存/转账)。

  3. Cancel:取消回滚

    • 如果 Try 失败或超时未确认,执行 Cancel 释放资源。

✦ 示例:

电商下单 → 减库存、扣余额、创建订单:

  • Try:冻结库存、冻结金额;

  • Confirm:真正扣除、生成订单;

  • Cancel:释放冻结。

✦ 优点:

  • 高灵活性、强一致性

  • 明确的业务隔离逻辑

  • 每个阶段幂等,便于容错处理。

✦ 缺点:

  • 实现成本高:需要为每个接口编写 Try、Confirm、Cancel 三个接口;

  • 资源浪费问题:预留资源可能一直未释放(如用户未支付);

  • 强依赖幂等、空补偿控制(如 Cancel 要能容忍资源未冻结的情况)。


四、Saga(编排型事务,补偿事务)

✦ 背景动机:

当业务流程长、参与节点多(如旅游、酒店、机票等),全局锁资源成本极高。Saga 采用 补偿思路,每个子事务成功后就执行下一个,如果某个子事务失败,就反向执行补偿。

✦ 操作流程:

  • 正向执行:T1 → T2 → T3 → T4

  • 若 T3 执行失败,则依次执行:C2 → C1(即对 T2、T1 的补偿操作)

每个 Tn 和 Cn 需要成对实现。

✦ 示例:

下订单:

  • T1:扣库存;

  • T2:扣余额;

  • T3:发短信通知 → 失败;

  • C2:退款;

  • C1:还原库存。

✦ 优点:

  • 非阻塞,异步执行;

  • 不需要锁全局资源;

  • 比 TCC 更灵活,适合长流程。

✦ 缺点:

  • 只能补偿,不能“真正回滚”,不是强一致;

  • 每个步骤必须实现 Cn 补偿逻辑;

  • 补偿可能失败(如库存补不回来);

  • 幂等、空补偿等问题依旧需要处理。


五、基于消息队列的事务消息(最终一致性)

✦ 背景动机:

适用于系统解耦、异步化场景,追求“最终一致性而非强一致性”,比如订单、发券、积分发放等。

✦ 操作流程(以 RocketMQ 为例):

  1. 生产者先发送“半消息”至 MQ;

  2. 本地事务执行(如写订单数据库);

  3. 成功后提交消息到 MQ,消费者才能收到;

  4. 若执行失败,回滚本地事务,并让 MQ 丢弃该半消息;

  5. 若网络异常,MQ 会回查本地事务状态。

✦ 优点:

  • 异步高性能;

  • 不阻塞主流程;

  • 适合最终一致的场景。

✦ 缺点:

  • 需要本地事务和消息发送保持一致性,对实现要求高;

  • 需要处理 MQ 消息幂等、顺序性、重复消费;

  • 不能保证强一致,只保证“最终一致性”。


总结对比(深入维度):

特性 2PC 3PC TCC Saga 消息队列事务
一致性 强一致 强一致 强一致 最终一致 最终一致
阻塞
容错能力 一般
实现复杂度
编程复杂度
恢复机制
适用场景 金融、支付 理论性 资源控制型业务 长流程补偿型 解耦+异步业务


网站公告

今日签到

点亮在社区的每一天
去签到