CDC、事件和投影:行变化不等于领域事实
CDC 捕获的是数据库行变化,业务看到的是"订单已取消"——update 一行可能是事务里第三次技术更新,不构成可公开的事件。本页定义快照与日志的衔接、版本守卫、删除墓碑与重建能力。位点与重放在消息侧的机制由 Kafka 消费位点与重平衡权威讲授;时间语义的完整推导见数据契约、时间语义与重建。
行变化与领域事实不是同一语义
CDC 捕获数据库日志或表变化并传播到消费者。消费者需处理重复、延迟、乱序、删除标记、schema 变化和初始快照与日志衔接。数据库提交顺序、binlog 顺序、事件分区顺序和投影应用顺序不是同一概念。投影应保存业务版本或源位点,只接受比当前新的一次更新;删除也需要 tombstone 或版本水位,避免旧事件复活已删数据。
可重建投影要求有权威事件或数据库快照、确定性转换、版本化代码和可追踪进度。若事件缺少重建所需字段,长期保留并不等于可恢复。事件契约应区分事件时间、处理时间、schema 版本和业务版本;消费者向后兼容并不保证新生产者事件对旧消费者的业务含义正确。
CDC记录源存储变化,领域事件表达业务动作;update一行不一定等于一次可公开的业务事件,事务内可能有多次技术更新。消费者需要知道事件身份、源位置、事务边界、对象版本、schema与删除语义,不能只传"id和新值"就承诺安全重放。Debezium MySQL文档解释快照、源日志位置和恢复;该链接为滚动文档,实际部署需再固定连接器版本,本文只使用通用恢复概念,不拼接某版内部调用链。
快照加增量的完整时序
记录可恢复的起始日志位置,取一致快照,随后应用覆盖快照期间变化的日志;切换时明确已追到的水位。先全表扫描、最后才记offset会漏掉扫描期间变更;先扫描一行旧值、实时事件写新值、回填旧值晚到则会覆盖新值,需要版本守卫。
教学投影操作为"若event.version大于当前版本则更新,否则幂等忽略";删除也写版本墓碑。相同版本不同payload是冲突,应报警核查而非静默选择。不同对象的版本不能直接比较,跨对象事务需要共同水位/事务信息或接受明确中间态。
业务恢复和容量算例
流入5000事件/秒,消费者处理6000,停机1小时产生1800万积压,理想净追赶1000/秒需5小时;日志保留必须覆盖停机、追赶与安全余量。只保留2小时日志,即使重启成功也可能在追赶前失去所需历史,需要重新快照。净追赶与清空时间的通用推导见队列网络、扇出与瓶颈迁移。
源offset已提交但下游写失败会丢投影;先下游提交再提交offset允许重复,因此需要幂等。把Kafka EOS用于两个Kafka事务域内输出,不能自动保证ES或外部数据库同步提交。毒事件需隔离、保留原始身份并可重放,不能直接跳过后宣称水位完整。
实验产物
用v1插入、v2修改、v3删除,按v2/v1/v3/v2顺序重放,最终必须为带v3墓碑的删除;再截断源日志,恢复器应明确请求快照而非猜测下一位置。提交快照范围、offset策略、乱序表、死信与重建时间。这些重放可在纸面或脚本完成,标为"模型推演";真实 CDC 管道本轮未运行。
领域事件与集成事件:内部事实不能原样外发
本页前面讲"行变化不等于领域事实",但没有回答另一个更容易犯的错误:领域事件也不等于集成事件。把上下文内部的领域事件直接发到消息总线,等于把内部模型永久暴露给所有消费者,之后任何字段调整都是破坏性变更。
两类事件的分工要写清楚。领域事件是上下文内的业务事实,可以携带内部结构(成本价、内部评分、策略版本),生命周期跟随模型演进;集成事件是跨上下文的发布语言,只包含稳定身份、版本、状态与少量必要字段,一旦发布就要按契约兼容规则演进。前者可以频繁调整,后者改动要走版本与迁移。
反例:订单上下文把 OrderSubmitted(含成本价与内部风控分)原样外发,通知、报表、风控三个消费者都开始依赖这些字段。半年后订单上下文要改成本模型,字段语义变化,三个消费者同时被破坏——这不是"事件驱动的好处",而是把内部实现变成了公共契约。
执行 python3 labs/context_model.py event_layers:模型把领域事件按发布语言字段集投影,预期输出集成事件只含 event_id/order_id/version/status,leaked_fields 为空,dropped_fields 为 cost_price_micros 与 internal_score。脚本只做字段投影,不验证序列化格式;真实契约兼容性由本页第 6 篇(数据契约)与 Avro 规范负责。
投影还有一个必须保留的东西:版本与身份。version=3 与稳定的 event_id 让消费者能去重与拒旧;把它们一起丢掉,集成事件就退化成"一条通知",无法支撑重放与对账。
两个合理选择:A 一个事件总线,领域事件直接外发,开发快但内部模型泄漏、演进受限;B 双层事件,领域事件在上下文内驱动聚合与投影,集成事件经发布语言投影后外发。本例选 B,代价是每个跨上下文消费者都要维护一份投影映射;收益是内部模型可以独立演进,消费者只依赖稳定契约。
架构师变化条件
把投影从"单对象版本守卫"改为"跨对象事务一致":需要共同源事务水位或显式中间态契约,单对象单调版本不再够用。若日志保留从 2 小时扩到 24 小时,磁盘与写入放大进入容量预算;追赶速度提高到 12000/秒则要看下游写吞吐与索引压力。删除请求加入合规时限时,墓碑保留期与重放窗口互相制约——每次变化重算"停机多久后必须重新快照"。
闭卷验收
本页 8 道闭卷题收进了下方自测面板:先回忆,再展开参考答案与评分点,最后给三档自评。