3. 分布式事务与一致性方案:两阶段提交、TCC、Saga、最终一致性
面试常见场景:支付订单跨库、账户扣款与订单状态同步、跨境汇款对账等。你需要根据业务场景(强一致性 vs 最终一致性)、响应时间要求、隔离级别容忍度,选择并解释合适方案。
3.1 高频面试问答卡片
🎯 面试问题1:描述两阶段提交(2PC)的工作原理及缺点。支付系统中何时会用到?
考察点:对一致性协议的理解;协调者故障处理;实际业务权衡。
回答框架: ① 简述2PC两个阶段(准备/提交) ② 指出缺点(同步阻塞、单点风险、数据不一致窗口) ③ 支付场景举例:跨行转账、账户余额与订单强一致,但仅在小并发核心链路使用。
2PC通过协调者收集所有参与者准备就绪后统一提交。缺点是协调者宕机时参与者会阻塞,且准备阶段锁定资源时间长。支付系统中,例如用户余额扣减与订单状态更新需要强一致时,会用Seata AT(基于2PC优化),但大多数场景改用TCC或Saga减少锁粒度。
可能追问: 如果协调者挂了,参与者一直“预提交”怎么办?如何实现协调者HA?
避坑提醒: 别只说缺点,要给出支付中实际使用场景(如对账、资金冻结)。强调必须配合超时和补偿机制。
🎯 面试问题2:TCC 模式的核心思想是什么?如何防止空回滚和悬挂?
考察点:补偿设计能力;空回滚、悬挂等边界情况处理;幂等实现。
回答框架: ① 分三步:Try预留资源 → Confirm执行 → Cancel补偿 ② 空回滚:Try未执行而Cancel已触发,需记录事务状态,若Try未完成则Cancel直接返回成功 ③ 悬挂:Confirm或Cancel先于Try到达,通过事务日志判断,拒绝无效调用。
TCC将业务拆为预留和执行。空回滚时在Cancel操作中检查事务记录,若Try不存在则返回成功。悬挂通过全局事务ID+阶段标记判断,仅允许合法顺序调用。支付中扣减优惠券用TCC预留,避免并发扣超。
可能追问: TCC的幂等怎么做?Try和Confirm/Cancel接口如何保证幂等?
避坑提醒: 不能只讲理论,需举例真实业务(如冻结金额、预占库存)。强调“业务隔离”与“资源预留”区别。
🎯 面试问题3:Saga 与 最终一致性分别适用什么场景?举例说明。
考察点:方案选型判断力;长事务处理;对账与重试设计。
回答框架: ① Saga适用于业务流程长、需要及时补偿的场景(如预订机票+酒店),分为编排和协同两种 ② 最终一致性适用于容忍短暂不一致、通过异步对账最终对齐的业务(如支付成功通知、积分发放) ③ 对比两者:Saga有正向/反向事务,最终一致性只保证数据最终正确。
Saga在支付中常用于跨机构转账(如提现到银行卡),每个步骤有补偿。最终一致性常用于用户下单后异步生成发票,依靠消息队列+本地事务表保证不丢。我曾在XX项目中用RocketMQ事务消息实现支付结果与积分发放最终一致,成功率达99.999%。
可能追问: Saga没有隔离性,如何处理脏读?本地消息表如何保证不重复?
避坑提醒: 不要混淆Saga和2PC:Saga无锁但需要补偿,2PC有锁但强一致。面试时举例要具体,带出业务理解。
3.2 公司侧重点 & 面试官画像
| 公司类型 | 面试侧重点 | 典型场景 |
|---|---|---|
| 互联网大厂(如阿里、字节) | TCC + Saga实际落地、Seata源码优化 | 支付交易、红包、秒杀库存扣减 |
| 金融科技 / 支付公司 | 强一致性方案 + 资金安全、对账设计 | 跨行转账、账户冻结、清结算 |
| 垂直电商 / O2O | 最终一致性 + MQ + 本地消息表 | 订单与积分、优惠券发放 |
面试官画像: 多为支付/交易后端架构师或小组长,8年以上经验。他们关注你能否从业务角度选择方案,而非背诵概念。常追问“如果此时XX挂了怎么办”,考验边界思考。
3.3 整体回答框架总结
1️⃣ 拆解需求 — 业务需要强一致还是最终一致?允许不一致窗口多长?
2️⃣ 方案匹配 — 短事务+强一致→2PC/TCC;长事务+可补偿→Saga;异步容忍→最终一致性。
3️⃣ 落地方案 — 必须讲清补偿机制、幂等、空回滚/悬挂处理,以及监控/对账。
3.4 项目案例 — 真实场景模板
| 项目名称 | 业务背景 | 规模指标 | 技术栈 | 核心难点 |
|---|---|---|---|---|
| 商户资金转账系统 | 为平台商户提供每日自动结算、提现到银行卡,需确保资金安全,支持撤销。 | 日交易量500万笔,单笔最大100万,TPS 2000。 | Spring Cloud, Seata TCC, MySQL, RocketMQ, Redis | 跨库转账无法用本地事务,需要分布式事务;撤销时需恢复所有中间状态;隔离性要求高。 |
面试高频追问
- Q: 为什么用TCC而不是2PC?
A: 2PC占用数据库锁时间长,并发低下。TCC在Try阶段只做资源预留(如冻结余额),业务层控制并发,转账失败时Cancel解冻。 - Q: 幂等和空回滚怎么保证?
A: 每条记录全局事务ID+操作类型唯一索引;Cancel前查询Try是否成功,否则直接返回成功不执行解冻。 - Q: 如果TCC的Confirm阶段失败怎么办?
A: 添加重试机制,设置最大重试次数(如3次),达到上限后写入死信表,告警人工介入补偿。
可迁移回答话术(面试可直接套用)
“在某商户结算项目中,我们用TCC实现了跨库转账。Try阶段冻结账户金额,Confirm时扣减并增加商户余额,Cancel时解冻。通过全局ID+状态机防止空回滚和悬挂,并用RocketMQ异步补偿,最终资金一致对账零差错。”
- 不要只说方案名称,必须解释为什么适合当前场景
- 不要忽略补偿/幂等,面试官最喜欢追问“挂了怎么办”
- 不要混淆TCC和Saga:TCC有资源预留,Saga直接执行+补偿
- 数据要具体:TPS、延迟、对账成功率等