CDC与Outbox面试题:MySQL同步ES、Redis、MQ的一致性
本页只放面试标准回答和原理跳转。完整链路、流程图、Demo 和 Runbook 见CDC与Outbox主线。
高频问题
| 面试题 | 标准回答 | 原理知识点 |
|---|---|---|
| CDC 和 Outbox 分别是什么 | CDC 是从数据库日志捕获已提交变更;Outbox 是业务事务内同时写业务表和事件表。Outbox 保证业务事实存在时事件意图也存在,CDC 负责把已提交事件可靠搬运到 MQ、ES、Redis 或其他视图。 | 概念区别 |
| 为什么不能直接双写 MySQL 和 ES | MySQL 和 ES 是两个提交边界,普通本地事务无法同时覆盖。MySQL 成功但 ES 失败会导致搜索旧值;ES 超时还会出现状态未知。正确做法是 MySQL 作为事实源,通过 Outbox/CDC/MQ 异步同步 ES,并支持重试、死信、重放和对账。 | 为什么需要CDC与Outbox、MySQL到ES |
| 捕获业务表和捕获 Outbox 表有什么区别 | 捕获业务表代码侵入少,但要从行变化推断业务语义,复杂聚合容易出错;捕获 Outbox 表由业务明确写领域事件,事件类型、主键、版本、载荷和重放策略清晰,更适合订单、支付、资产、权限和搜索同步。 | 两种CDC模式 |
| ES 更新失败怎么办 | 不把失败吞掉。网络超时按状态未知重试;ES 429退避限速;Mapping冲突进死信并修正索引;旧事件晚到用版本判断忽略;长期不一致按MySQL事实源补偿或重建索引。 | ES同步链路、ES没更新Runbook |
| Redis 缓存删除失败怎么办 | 常见组合是事务提交后主动删除缓存,失败记录重试;CDC订阅MySQL变化作为兜底再次删除相关key;缓存设置TTL最终兜底。缓存不是事实源,关键交易判断要回数据库或业务服务。 | Redis缓存同步 |
| CDC 为什么仍然会重复和乱序 | CDC、MQ、消费者确认通常是至少一次语义,位点提交、发送确认、消费ACK任何一步状态未知都可能重复;不同分区、重试、失败恢复会导致乱序。消费者要用eventId去重,用aggregateVersion防止旧事件覆盖新状态。 | 顺序重复乱序 |
| 事件里为什么要有 version | version 表示业务聚合版本,用来处理乱序和旧事件覆盖。比如 ES 已经更新到商品 version=9,晚到的 version=8 事件必须忽略,否则搜索视图会回退到旧状态。 | 事件模型、版本幂等Demo |
| CDC Lag 变大怎么排查 | 查数据库日志产生速度、CDC连接和解析线程、序列化耗时、MQ写入、单表大事务、大字段事件、消费者处理耗时和下游ES/Redis/DB限速。扩容前要确认分区、业务key和下游容量。 | CDC Lag Runbook |
| 重放消息要注意什么 | 先确定事实源范围、起止位点或业务版本,再按eventId和version幂等重放,记录成功、失败和死信,最后对账目标视图。不能无范围、无版本地全量乱发,否则可能造成旧事件覆盖新数据。 | 位点和重放 |
| CDC/Outbox 能保证强一致吗 | 不能。它们解决的是可靠传播和最终一致,不是跨MySQL、ES、Redis、MQ的原子提交。短暂不一致是允许的,但必须有重试、死信、补偿、重放、对账和监控,避免短暂不一致变成永久错误。 | 本章小结 |
场景题
1. 面试官问:MySQL 更新成功,但 ES 更新失败怎么办
标准回答:
我会先明确 MySQL 是事实源,ES 是可重建搜索视图。写接口只保证 MySQL 事务提交,并在同一事务写 Outbox 事件;CDC 捕获事件后投递 MQ,ES 消费者按业务主键和版本幂等更新。ES 更新失败不吞掉,网络超时重试,429退避限速,Mapping冲突进死信,长期不一致通过对账任务按 MySQL 事实源重建文档。排查时看 MySQL 版本、Outbox、CDC位点、MQ offset、消费日志、死信和 ES 文档版本。
原理入口:MySQL到ES同步链路。
2. 面试官问:为什么有了 CDC 还要 Outbox
标准回答:
直接捕获业务表只能看到行发生变化,不一定知道领域语义。比如商品表价格、上下架、库存、描述变化,对下游事件含义不同;多表聚合更难判断。Outbox 由业务在本地事务里显式写领域事件,事件类型、业务主键、版本和载荷清晰,CDC 只负责可靠搬运。这样更适合可审计、可重放、可演进的商业系统。
原理入口:捕获业务表和捕获Outbox。
3. 面试官问:消息重复和乱序怎么保证最终一致
标准回答:
首先承认 CDC/MQ 是至少一次语义,会重复、乱序、延迟。消费者用 eventId 做消费去重,消费日志和业务写入尽量同事务;同一业务聚合用 aggregateVersion 做版本判断,新版本覆盖旧版本,旧版本晚到忽略;需要顺序的场景按 aggregateId 做分区 key。失败进入重试、死信和对账,不能靠“消息只来一次”保证正确。
原理入口:顺序、重复和乱序。
面试回答模板
text
CDC是从数据库日志捕获已提交变化,Outbox是业务事务内同时写业务表和事件表。生产里常用“业务写Outbox,CDC搬运Outbox”,这样事件语义清晰且业务提交后一定有待传播事件。它解决的是数据库到MQ、ES、Redis等派生视图的可靠最终一致,不是跨系统强一致。链路仍然至少一次,所以消费者必须用eventId去重,用businessKey和version处理乱序,用schemaVersion处理事件演进。MySQL到ES不一致时,我会查MySQL事实源版本、Outbox事件、CDC位点、MQ offset、消费日志、死信和ES文档版本,必要时按事实源重放或重建。本章小结
CDC/Outbox 面试不要只说“订阅 binlog”。要讲清事实源、事件语义、位点恢复、至少一次、幂等、版本、Schema、死信、重放和对账,这样才是真正的生产级答案。
