跳到主要内容
约 4 分钟2 张卡

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 行变更与业务事件​

11 · 面试题卡片​

11.1 本地事务提交后消息发送失败,如何保证最终发布​

出现公司:暂无已核验的公开来源(本站自测)

题型:综合题

考察重点

  • 数据库与 broker 双写窗口。
  • Outbox 本地原子提交和 relay 重复发送。
  • CDC offset、聚合顺序和消费幂等。

相关内容:双写窗口至监控。

参考回答

业务状态与 Outbox 记录应在同一事务提交。

提交成功后,事件有持久来源。独立 relay 轮询或通过 CDC 发布,失败后继续恢复。

发送成功而确认丢失会导致重复。消费者用 Inbox 或业务幂等约束效果。聚合 key、发布顺序与版本共同处理乱序。监控最老事件、日志滞后和消费差异,以发现停滞。

11.2 同一聚合使用相同消息 key 后,为什么仍需检查版本和发布顺序?​

出现公司:暂无已核验的公开来源(本站自测)

考察重点:分区顺序、并行发布与增量事件缺口。

相关内容:版本缺口与事件类型。

参考回答

相同 key 控制分区路由,分区只保留实际追加顺序。

两个 relay 仍可先发送版本 12,再发送 11。完整快照可按版本拒绝旧值。增量事件则需补齐缺口,避免漏算。发布端与消费端都需维护聚合内顺序。

12. 参考资料​