Sunday面试指南

分布式事务怎么实现?2PC、TCC、Saga 有什么区别?

🧑‍💻 面试官:跨服务事务怎么处理?

🙋‍♂️ 我:用 Saga,失败时回滚。

🧑‍💻 面试官:第一步已经发送邮件,第二步失败,怎么把邮件回滚到没发过?

🙋‍♂️ 我:只能补偿,不能撤销已经发生的事实。

🧑‍💻 面试官:那 2PC、TCC、Saga 和 Outbox 分别解决什么,能随意互换吗?

先确定需要共同提交,还是允许已提交步骤再补偿;补偿不是把时间倒回去。

面试速答(60 秒版)

跨服务各自使用本地事务,无法直接靠一个普通数据库事务覆盖全部资源。2PC 让支持协议的参与者准备后统一决定提交或回滚,但有协调、等待和恢复成本。

TCC 由业务实现 Try 预留、Confirm 确认、Cancel 取消,设计幂等和资源状态的负担更明显。Saga 把流程拆成已提交的本地事务,失败时执行业务补偿,没有通用的全局隔离与物理回滚保证。

Outbox 用同一份本地事务保存业务变化和待发事件,解决相关双写窗口;投递可能重复,消费者仍需幂等。

选择看不变量、资源能否预留、是否允许中间状态和补偿,不能只因为微服务就默认选 Saga。

四类方案处理不同层次的提交、预留、补偿与发布问题

知识点详解:共同决定和事后补偿是不同承诺

先承认两个数据库之间有故障窗口

假设服务 A 保存任务后,要通知服务 B 分配资源。先写 A 再发消息,进程可能在中间退出;先发消息再写 A,也可能消息已经生效但本地写入失败。

这不是给接口包一层 try/catch 就能消失的问题。网络超时还会让你不知道对方到底执行了没有。

因此要先定义成功状态和不变量,再选择协调或异步恢复机制。

2PC 与 TCC 都有准备阶段,但资源层次不同

2PC 的参与者进入准备状态,再由协调者决定结果。以支持准备事务的数据库为例,等待期间可能继续持有锁,协调者状态与恢复不能丢。

TCC 把预留和确认表达成业务操作,例如先预留某份配额,成功后确认使用,失败后释放。它不要求所有资源都只靠相同数据库指令操作。

Try、Confirm、Cancel 需要应对重试、乱序和失败状态。迟到的 Try 不能把已取消事务重新占住,重复 Confirm 不能重复扣资源。

Saga 的补偿,是新的业务动作

假设先保存任务、再开通资源,后一步失败,可以将任务标为失败并释放已开通资源。先前提交过的记录不必假装没存在过。

如果中间已经对外发送通知,补偿可能是再发更正,而不是把原通知撤销。补偿自身也可能失败,需要重试、报警或人工介入。

Saga 的编排器与事件协同各有复杂度,但都要定义状态和补偿。没有明确补偿能力的动作不能随意当作可逆步骤。

Outbox 解决事件发布,不直接变成全局事务

把本地业务更新和事件记录放在同一事务里,后台读取已提交事件并发送。这样能恢复“业务已完成,事件尚未发出”的窗口。

发送完成后记录进度之前退出,会再次发送。因此消息 ID、消费者幂等、顺序和重复处理仍要设计。

Outbox 可以服务于 Saga 等架构,但它自己不保证所有服务一起提交。验收要注入超时、重复投递、协调者退出和补偿失败,而不只跑正常路径。

本题机制参考:PostgreSQL 准备事务、Apache Seata TCC、AWS Saga 编排、Transactional Outbox 原作者说明。

本地事务共同保存业务和事件,后台发布仍有重复投递窗口

面试官继续追问

Saga 能保证全局数据库隔离吗?

通常不能按普通单库事务理解。中间步骤已提交,其他操作可能观察到,需要业务隔离策略。

2PC 没有任何失败风险吗?

不是。需要持久化决策、参与者恢复和协调故障处理,长时间准备还会占资源。

Outbox 投递算恰好一次吗?

不能默认。发送与记进度之间仍有重复窗口,效果去重要由消费者等机制保障。

面试速记卡

  • 2PC:支持协议的资源准备,再统一决定。
  • TCC:业务预留、确认、取消,状态与幂等自己设计。
  • Saga:本地提交+业务补偿,不是倒带。
  • Outbox:业务和事件同库事务,投递仍可能重复。
  • 选型:不变量、资源预留和中间状态容忍度。

公司面试真题

真题根据求职者公开面经整理,题意经过概括,非逐字原话或公司官方题库;本文为 Sunday 的独立解析。

浏览公司面试真题 →
简历汪永久免费在线制作简历,模板直接套用、导出无水印,永久免费、下载免费,不需要付费解锁任何功能。去写简历