60 秒回答模板

最终一致性不是简单说“用 MQ”。我会先定义业务允许的不一致窗口和最终正确状态,再让本地业务变更和待发送事件在同一个事务里落库,例如 outbox 消息表或事务消息。消息投递后消费者必须幂等,能处理重复、乱序和超时;失败要有指数退避重试、死信告警和人工兜底。最后用状态机、补偿任务和定时对账发现长期卡住的数据,把临时不一致收敛到终态。

考点 核心机制与工程取舍
难度 中高频面试题
回答目标 按定义、机制、场景讲清楚

深入解析

01

先定义一致性目标

回答要先说清哪些状态允许延迟一致、最长延迟多久、最终以哪个系统为准。订单支付、库存、账户余额这类关键状态通常要有明确终态和审计记录;通知、统计、搜索索引等可以接受更长的一致性窗口。

02

保证事件不丢

最常见风险是数据库事务提交了,但消息发送失败,或者消息发出后业务事务回滚。工程上可以把业务数据和 outbox 事件放在同一个本地事务里提交,再由后台任务或 CDC 投递;也可以使用事务消息,但仍要处理确认失败和回查。

03

消费者必须幂等

消息系统通常只能承诺至少一次投递,所以消费者要用业务唯一键、去重表、唯一索引、状态机版本或乐观锁保证重复消费不会重复扣款、发货或推进状态。幂等不是只判断消息 ID,还要和业务状态转移绑定。

04

失败要能收敛

消费失败不能无限静默重试。短暂故障用有限重试和退避;持续失败进入死信队列并告警;可自动修复的场景用补偿任务重新投递、逆向操作或推进状态;不可自动判断的场景保留人工处理入口和审计线索。

05

用对账兜底

最终一致性需要发现长期不一致,而不是只依赖实时链路成功。定时对账按权威状态扫描支付、订单、库存、发券等数据,找出卡在中间态或两边不一致的记录,再通过补偿任务修复,并把超出一致性窗口的比例纳入监控。

易错点

  • 只回答“用 MQ 异步处理”,没有解决业务事务成功但消息丢失的问题。
  • 把重试当成万能方案,却没有幂等键、状态机校验和最大重试边界。
  • 没有定义一致性窗口,导致无法判断多久算正常延迟、多久要告警。
  • 缺少对账和补偿,实时链路一旦漏单就永久不一致。

面试官追问

本地事务和发消息怎么保证不割裂?

把业务变更和事件记录放到同一个数据库事务里提交,事务成功后再异步投递事件;投递失败时事件仍在表里,可以重试或由 CDC 补发。事务消息也能解决类似问题,但要实现回查和异常确认。

为什么最终一致性一定要讲幂等?

因为超时、重试和 Broker 至少一次投递都会让同一业务事件被处理多次。没有幂等,重试本来是修复手段,反而会造成重复扣减、重复发券或状态越级。

补偿和回滚有什么区别?

回滚通常发生在同一个事务边界内,直接撤销未提交或刚提交的操作;补偿是分布式链路已经部分成功后,用新的业务动作把状态修正回来,必须考虑幂等、审计和用户可见状态。

如何判断最终一致性方案是否可靠?

看四个指标:事件积压和投递失败率、消费重试和死信数量、超过一致性窗口的数据量、对账修复成功率。只讲架构不看这些指标,线上不可运营。