Transactional Outbox 与 CDC
Transactional Outbox 让业务变化和事件共同提交。CDC 可从提交日志中提取事件。本文讲解双写窗口、发布恢复和事件顺序。
1. 面试核心
先记住这几条,再读正文- 本地原子提交。 Outbox 把业务状态与待发事件写进同一本地事务。卡 · 综合题
- 重复交付。 relay 在发送后、记录结果前崩溃,会造成重复交付。
- CDC 恢复位置。 CDC 的恢复依赖提交日志和持久化消费位置。
- 聚合内顺序。 相同聚合键路由到同一分区,业务顺序仍需发布端串行约束。卡 · 版本缺口与事件类型
- 消费端去重。 Inbox 去重记录与消费结果共同提交,可限制本地重复效果。
2. 双写窗口
普通双写有两个独立提交点:
提交数据库 → 发送消息
数据库成功而发送失败,下游会漏掉变化。交换顺序后,消息成功而数据库回滚,下游会处理无效事实。异常重试仍会遇到进程在两步之间退出。
3. Outbox 表
业务事务同时写订单与 Outbox。示例字段如下:
event_id, aggregate_type, aggregate_id, aggregate_version,
event_type, schema_version, payload, created_at
事件记录已发生的业务事实。event_id 用于去重,aggregate_version 用于检查实体顺序。schema_version 支持契约演进。payload 只保留消费所需字段。
本地事务提交时,两份记录共同持久化。事务回滚时,两者共同撤销。
4. 轮询 relay
relay 领取待发布记录,发送到 broker,再记录发布结果。轮询方案可另设 published_at、租约和重试字段。
多个 relay 可用分片或 SKIP LOCKED 分配工作。发送成功后尚未标记就崩溃,会再次发送。先标记后发送,则会在崩溃时漏消息。因此消费端需要幂等。
领取记录还需处理租约过期和工作进程退出。索引、批次上限与历史清理控制数据库负载。
5. CDC
CDC 从数据库提交日志获取变化。MySQL 使用 binlog,PostgreSQL 可使用逻辑解码。连接器把 Outbox 插入映射为消息。
连接器保存日志位置,并从该位置恢复。日志保留期需覆盖停机和追赶耗时。日志已被清理时,需要按连接器方案重建快照或补数据。
Debezium Outbox Event Router 映射 key、header 与 payload。CDC 表以插入事件为主。轮询方案的发布标记更新,应与所选转换器规则区分。
6. 按聚合键排序
同一订单使用相同 aggregate_id 作为 Kafka key。在固定分区映射下,它们进入同一分区。分区保存实际追加顺序。
同一聚合的版本还需由数据库并发控制生成。自增 Outbox ID 反映分配顺序,未必反映提交顺序。多 relay 并发也会改变发送顺序。
6.1 版本缺口与事件类型
假设订单版本 12 先到,版本 11 后到。版本 12 若包含完整投影,消费者可条件更新到 12。之后到达的旧快照可以忽略。
若事件只是“余额增加 10”,跳过旧版本会漏算。增量事件应按连续序号处理。发现缺口时暂停该聚合,并补取或重放缺失事件。
发布端可按聚合分片并串行发送。消费者也需避免并行处理打乱副作用。相同 key 只负责路由,完整顺序取决于整条链路。
7. 消费者幂等
消费者把 event_id 写进 Inbox 唯一表。Inbox 与本地业务变化在同一事务提交。重复事件返回已有处理结果。
邮件、扣款等外部副作用需要对方的幂等键。去重记录保留期和历史重放见分布式流程恢复。
8. 发布与业务完成
Outbox 保证本地变化留下待发记录。最终送达还依赖 relay 恢复、日志保留和 broker 持久性。
发布完成后,下游仍需消费。跨服务流程按必要参与者的结果推进。接口若只承诺受理,应明确返回处理中。
9. 监控
发布端监控最老未发布事件年龄与失败次数。CDC 监控日志位置、滞后和保留空间。消费端监控积压、死信和版本缺口。
进程存活却持续卡在一条事件时,业务仍会停滞。对账可检查业务记录与事件的对应关系。
10. 常见问题
10.1 Outbox 与 exactly-once
Outbox 保护本地原子提交。发送响应丢失后,事件仍可重复。端到端业务效果需要消费者与外部目标共同约束。
10.2 行变更与业务事件
整表 CDC 能捕获行变化。业务事件则表达稳定事实,例如“订单确认”。显式 Outbox 可以隔离内部表结构的变化。
11 · 面试题卡片
11.1 本地事务提交后消息发送失败,如何保证最终发布
出现公司:暂无已核验的公开来源(本站自测)
题型:综合题
考察重点
- 数据库与 broker 双写窗口。
- Outbox 本地原子提交和 relay 重复发送。
- CDC offset、聚合顺序和消费幂等。
参考回答
业务状态与 Outbox 记录应在同一事务提交。
提交成功后,事件有持久来源。独立 relay 轮询或通过 CDC 发布,失败后继续恢复。
发送成功而确认丢失会导致重复。消费者用 Inbox 或业务幂等约束效果。聚合 key、发布顺序与版本共同处理乱序。监控最老事件、日志滞后和消费差异,以发现停滞。
11.2 同一聚合使用相同消息 key 后,为什么仍需检查版本和发布顺序?
出现公司:暂无已核验的公开来源(本站自测)
考察重点:分区顺序、并行发布与增量事件缺口。
相关内容:版本缺口与事件类型。
参考回答
相同 key 控制分区路由,分区只保留实际追加顺序。
两个 relay 仍可先发送版本 12,再发送 11。完整快照可按版本拒绝旧值。增量事件则需补齐缺口,避免漏算。发布端与消费端都需维护聚合内顺序。