JJava 知识库
JAVA INTERVIEW

高频面试题

架构高级约 3 分钟

下单需要同时扣库存、用优惠券和创建支付单,跨服务事务怎么保证最终一致?

参考回答约 3 分钟 · 口语表达
先说结论

我会先定目标和容量,再拆核心链路:分布式事务没有通用最优解。强一致且参与者支持协议时可评估 2PC;业务可提供预留、确认、取消接口时可用 TCC;长流程适合 Saga 补偿;可接受最终一致的事件驱动业务常用本地事务加 Outbox 或可靠消息。 首选仍是调整服务和数据边界,让一次事务在单库或单聚合内完成,避免不必要的跨服务原子性。

01

我不会直接画架构图,会先确认目标、规模和一致性要求。比较 2PC、TCC、Saga 和可靠消息的适用边界与工程成本。分布式事务没有通用最优解。强一致且参与者支持协议时可评估 2PC;业务可提供预留、确认、取消接口时可用 TCC;长流程适合 Saga 补偿;可接受最终一致的事件驱动业务常用本地事务加 Outbox 或可靠消息。 首选仍是调整服务和数据边界,让一次事务在单库或单聚合内完成,避免不必要的跨服务原子性。

02

容量有了以后,再把入口、核心处理和数据落点串起来。沿着「定义跨服务不变量 → 本地事务落状态与事件 → 异步驱动后续步骤 → 失败补偿或重试 → 对账确认最终收敛」观察输入、状态与输出,这些阶段都可以从日志、指标或源码里验证。 定义跨服务不变量 先识别必须原子的不变量与允许的中间状态,避免一开始就要求所有服务强一致。 本地事务落状态与事件 每个服务只在自己的数据库完成本地事务,Outbox 可把状态与待发布事件原子写入。 transaction/outbox 状态表:全局步骤证据。 补偿流水 UNIQUE(txid,step):幂等补偿。 我会先确认请求实际走到了哪条路径,再用运行数据验证,不会只看类名或配置猜测。

03

关键参数要从峰值流量和资源上限反推。是否先明确一致性强度、业务边界和失败模型。 能否比较 2PC、TCC、Saga 与可靠消息。 是否把幂等、补偿、重试和对账纳入方案。

04

正常链路之外,还要设计失败补偿和可验证的恢复流程。订单取消事件发送失败,券服务没有收到补偿。订单状态正确但全局事务未闭环。通过事务 Outbox、补偿状态机和超时扫描重发后,失败窗口可恢复。 补偿操作无幂等导致重复退款:各状态停留时长:每步持久状态机。 只发 MQ 不解决本地提交与发送窗口:事件投递重试:补偿也幂等。 全局状态机没有超时终态:补偿成功率:超时扫描+人工终态。 固定输入和基线 先在没有故障注入的环境执行上述配置,固定数据规模、并发度、运行时版本和预热时间。以「状态超时数」为主基线,记录值应满足「记录活动/稳态基线」;同时保存 各状态停留时长、事件投递重试,使后续变化能够回到同一时间轴比较。

05

最后再讲扩容、成本和方案边界。方案:一致性:可用性成本:业务侵入:适用场景。 2PC/XA:较强:协调者故障可能阻塞:中:参与者少且都支持协议。 TCC:业务可控:需要预留与补偿:高:资金、库存等可拆三阶段动作。 Saga:最终一致:分步提交,可补偿:中高:长流程、每步可逆或可补偿。 Outbox/可靠消息:最终一致:高可用、异步:中:事件驱动、允许延迟收敛。

方案主链路从目标到落地
01定义跨服务不变量
02本地事务落状态与事件
03异步驱动后续步骤
04失败补偿或重试
05对账确认最终收敛