这本书的骨架
卷三回答一个问题:怎么用事件设计系统,而不是用消息替代 RPC。
这个问题不能靠一章讲完,因为它有三层:先要判断「该不该用事件」,再要设计「事件长什么样、谁来消费」,最后要解决「跑起来之后怎么治理」。所以全书按「范式 → 一致性与演进 → 流处理 → 可观测与治理 → 案例与验收」分五部分。
| 部分 | 章节 | 回答的问题 |
|---|---|---|
| 第一部分 范式 | 第 1–3 章 | 什么时候该用事件?事件怎么建模?CQRS 的边界在哪? |
| 第二部分 一致性与演进 | 第 4–6 章 | 跨服务怎么一致?顺序与并发怎么处理?契约怎么演进? |
| 第三部分 流处理 | 第 7–9 章 | Streams 的拓扑、状态、窗口怎么用?作业怎么运维? |
| 第四部分 可观测与治理 | 第 10–12 章 | 事件流怎么监控?平台怎么治理?怎么从现状迁移? |
| 第五部分 案例与验收 | 第 13–15 章 | 完整链路长什么样?不同场景怎么选?上线判据是什么? |
前三部分是「设计」,第四部分是「运营」,第五部分是「收束」。只读前三部分能画出正确的架构,只读第四部分能在出事后定位,两者都读才谈得上可落地。
每一章回答的那个问题
十五个章节,每章只回答一个问题。这是写作时的取舍标准——凡是不能回答这个问题的内容,都不写进这一章。
| 章 | 问题 |
|---|---|
| 1 | 事件、命令、查询,三者到底差在哪? |
| 2 | 一个业务变化,应该拆成几个事件? |
| 3 | 读写分离到什么程度才叫 CQRS? |
| 4 | 跨服务的一致性,有哪几种落地方式? |
| 5 | 分区有序、业务有序、因果有序,是同一件事吗? |
| 6 | 事件契约改了,老消费者怎么办? |
| 7 | Kafka Streams 的拓扑到底是一张什么图? |
| 8 | 流和表为什么是同一件事的两种看法? |
| 9 | 流作业重启、扩容、卡住时会发生什么? |
| 10 | 一条事件跨越五个主题,怎么追? |
| 11 | 几十个团队共用一个事件平台,怎么管? |
| 12 | 从单体迁移到事件驱动,第一刀切在哪? |
| 13 | libraryd 的完整链路长什么样? |
| 14 | 库存、游戏、IoT 的场景和业务事件有什么不同? |
| 15 | 一条事件链路能不能上线,用什么判据? |
前置:三篇必须先读的
| 篇 | 标题 | 作用 |
|---|---|---|
| 序 | 别把消息队列当 RPC | 三种误用;五条立场;五个自检问题 |
| 前言 | 实验环境、Kafka Streams 与案例口径 | 机器与依赖;最小拓扑验证;架构图画法;验证规矩 |
| 本节 | 目录与学习路径 | 全卷地图与三条读法 |
前两篇加起来不到六百行,但它们决定了后面四十五章的可信度。序告诉你「为什么消息队列不等于事件驱动」,前言告诉你「怎么验证书上的输出」。跳过它们的读者,往往会在第一次跑不通依赖时怀疑书。
第一部分:范式(第 1–3 章)
这一部分建立共同语言。读完它,你应该能在设计评审上准确说出「这是命令不是事件」「这个场景不该用 CQRS」。
第 1 章 三种交互
- 1.1 事件、命令与查询 —— 三者语义差异;事件是过去时且可多播,命令是祈使且应单接收;混用的后果。
- 1.2 事件驱动 vs 请求驱动 —— 什么时候该用事件,什么时候不该;决策树与两个反例。
- 1.3 事件驱动成熟度模型 —— 五级成熟度;每级的能力与成本;自评表。
第 1 章的核心不是定义,是判断。1.1 给出三个 libraryd 事件的对比,1.2 给出可执行的决策树,1.3 让读者先给自己定位。
第 2 章 事件建模
- 2.1 领域事件识别 —— 从业务动作与状态变化里找事件;事件不等于表变更;命名规范。
- 2.2 事件边界与聚合 —— 聚合根决定事件粒度;一个聚合一次事件;跨聚合用事件而非共享表。
- 2.3 事件目录与契约 —— 事件目录该记什么;生产者与消费者的契约;谁有权改。
这一章的立场:事件粒度由聚合边界决定,不由数据库表决定。 2.3 给出一份可直接维护的 events.yaml 目录。
第 3 章 CQRS
- 3.1 CQRS 的基础形态 —— 写模型与读模型分离;不是必须两套库;适用边界。
- 3.2 读模型投影 —— 消费者维护投影表;幂等写入;投影延迟。
- 3.3 投影重建与重放 —— 重置位移重放;重建期间的读服务;双写切换。
3.2 和 3.3 都有可运行的投影代码与重建实验,不是结构图讲解。
第二部分:一致性与演进(第 4–6 章)
这一部分处理「多个服务、多个事件之间」的问题:事务怎么办、顺序怎么保、契约怎么改。
第 4 章 一致性
- 4.1 分布式事务的三种落地 —— 2PC、TCC、最终一致;每种的前提与代价。
- 4.2 本地消息表与对账 —— outbox 的工程化;对账任务兜底。
- 4.3 补偿与最终一致性 —— 补偿的触发条件;补偿失败的人工出口;一致性窗口的承诺。
4.2 会把对账任务真跑一遍,构造三类差异并输出差异报告。
第 5 章 顺序与并发
- 5.1 事件顺序与业务顺序 —— 分区有序不等于业务有序;因果序;用版本号而非时间戳排序。
- 5.2 幂等边界的设计 —— 幂等键选什么;跨聚合的幂等;与「至少一次」的配合。
- 5.3 并发控制与版本 —— 乐观并发与事件顺序;冲突处理策略。
5.3 会做一次「两个消费者同时改同一个聚合」的实验,看版本号怎么把冲突变成可处理的失败。
第 6 章 契约演进
- 6.1 事件版本化 —— 版本放哪(主题/信封/字段);何时需要新主题。
- 6.2 消费者兼容性策略 —— 新老消费者共存;容忍未知字段;默认值。
- 6.3 破坏性变更的迁移 —— 双写、影子消费、灰度切换、下线旧主题。
这一章回答的是组织问题,不只是技术问题:谁有权改一条已经在被消费的事件。
第三部分:流处理(第 7–9 章)
这一部分用 kafka-streams:4.3.0 实跑,不引入其它流处理框架。
第 7 章 Streams 基础
- 7.1 Kafka Streams 的拓扑模型 —— 拓扑、处理器、源/汇;Streams 与普通消费者的区别。
- 7.2 有状态处理与状态存储 —— 状态存储、changelog 主题、本地恢复。
- 7.3 窗口与时间语义 —— 事件时间 vs 处理时间;窗口类型;迟到数据与宽限期。
7.3 会把三种窗口各跑一遍,贴出触发时刻与迟到数据的处理结果。
第 8 章 流表模型
- 8.1 流表二元性 —— KStream 与 KTable 的互相转换;流是表的变化日志。
- 8.2 连接与聚合 —— join 的对齐与窗口;聚合的 key 选择;重分区。
- 8.3 处理语义与恰好一次
—— Streams 如何做事务;
processing.guarantee;与外部副作用的边界。
第 9 章 流作业运维
- 9.1 流作业的部署与运维 —— 实例数、任务分配、再平衡;升级时的状态兼容。
- 9.2 状态恢复与再平衡 —— 状态恢复的耗时;standby 副本;恢复期间的处理暂停。
- 9.3 资源与背压 —— 缓存大小、提交间隔;消费滞后与处理延迟的区分。
第 9 章是卷三最容易出事故的地方:流作业的重启不是无状态的,状态恢复时间直接决定停机窗口。
第四部分:可观测与治理(第 10–12 章)
第 10 章 可观测
- 10.1 事件链路的追踪 —— 事件头的 trace 传递;跨主题的链路;采样。
- 10.2 端到端延迟度量 —— 生产时间戳到消费完成;各段拆解;分布而非均值。
- 10.3 事件血缘与影响分析 —— 谁生产、谁消费;变更影响面;血缘的自动收集。
第 11 章 平台治理
- 11.1 事件平台自助化 —— 建主题、申请权限、查血缘的自助流程;审批点放哪。
- 11.2 Topic 命名与生命周期 —— 命名规范;创建、演进、下线;孤儿主题清理。
- 11.3 配额与成本分摊 —— 按业务线分摊存储与流量;配额与成本的关系。
第 12 章 方法与迁移
- 12.1 事件风暴工作坊 —— 如何组织一场事件风暴;产出物;常见失败。
- 12.2 从单体到事件的迁移 —— 从哪里切第一刀;绞杀者模式;双写过渡。
- 12.3 反模式清单 —— 十二条反模式与后果分级。
第 12 章是全书的「反面教材汇总」,12.3 的十二条可以直接拿去评审。
第五部分:案例与验收(第 13–15 章)
第 13 章 libraryd 全链路
- 13.1 libraryd 领域建模 —— 聚合、事件、读模型;边界划分的理由。
- 13.2 借阅事件的完整链路 —— 借阅→库存→预约→通知;每个消费者的职责;失败处理。
- 13.3 逾期提醒:定时与事件 —— 定时扫描 vs 事件驱动;延迟事件的实现;重复提醒的抑制。
第 14 章 场景对照
- 14.1 库存类场景 —— 超卖、预占、释放;库存事件的顺序与幂等。
- 14.2 游戏与 IoT 场景 —— 高频小消息、设备离线、乱序到达;与业务事件的区别。
- 14.3 架构评审清单 —— 二十五条评审问题,按契约、一致性、运维、成本分组。
第 15 章 上线与验收
- 15.1 SLO 与容量 —— 事件链路的 SLO 怎么定;延迟与新鲜度;容量与 SLO 的关系。
- 15.2 故障演练剧本 —— 四个剧本:broker 挂、消费者挂、投影错、契约破坏。
- 15.3 全书验收 —— 三卷的验收汇总;遗留风险;后续演进方向。
15.3 会把三卷的实验与产物汇总成一张索引表,并明确列出哪些结论仍然依赖真实环境验证。
附录
- 附录 A 术语表 —— 六十条事件驱动术语,中英对照、一句话定义、易混词辨析。
- 附录 B 架构决策记录模板 —— 五份 ADR 模板:选型、契约、一致性、迁移、治理。
三条阅读路径
架构师路径:序 → 第 1–3 章 → 第 13–15 章。
先建立判断(什么场景用事件、事件怎么建模、CQRS 到什么程度),再看完整案例(libraryd 全链路),最后看验收判据。第 4–6 章可以略读,需要时再回来。
开发路径:前言 → 第 2–4 章 → 第 7–9 章。
重点在可运行的部分:事件 record 怎么定义、投影消费者怎么写、Streams 拓扑怎么搭。第 10–12 章可以留到上线前再读。
评审路径:目录 → 第 10–12 章 → 第 14–15 章。
用第 14.3 的二十五条评审问题当检查表,配合第 15.1 的 SLO 表和第 15.2 的演练剧本,组成上线评审的完整材料。
哪些章节可以跳读
- 只做业务事件、不做流处理:第 7–9 章可以整章跳过,但 8.1 的流表二元性建议读——它解释了「事件日志为什么能当表用」。
- 已有成熟事件平台:第 11 章可以略读,重点看 11.2 的命名与生命周期。
- 不做 CQRS:第 3 章可以跳,但 3.3 的「重放重建」值得读——它是事件溯源的入口。
- 必读:第 1 章、第 2 章、第 5 章、第 6 章。这四章决定了后面所有设计的正确性。
三条路径之外的读法
如果时间只够读一篇,读 1.1。它用三个 record 把事件、命令、查询的区别摆在代码层面,是全书共同语言的起点。
如果只够读一章,读第 2 章。事件建模错了,后面的 CQRS、流处理、契约治理都是在错误的基础上加固。
如果只够读一部分,读第一部分。范式判断错了,工具用得再熟也只是把错误放大。
三种读法之外,还有一种更实用的用法:把它当手册。 遇到具体问题时,从章标题里找一个最接近的,直接跳进那一节的「判据」部分,再回头读论证。目录里的每条摘要都写了该节的可验证物,方便判断值不值得读全文。
手册式读法的前提是目录准确。所以这一页会随着正文落盘持续校正——如果某节的标题或摘要与实际内容不符,以正文为准,目录会被修改。
每节末尾的判据怎么用
卷三的每一节结尾都会有一条判据。它们不是总结,是可以在评审会上直接念出来的句子。三种用法:
设计时当检查表。 画完架构图,逐条对照:这条链路有没有明确「谁是生产者、谁是消费者」?事件粒度是按聚合还是按表?重放三个月前的数据能不能重建读模型?答不上来的地方就是设计缺口。
评审时当提问清单。 第 14.3 节把二十五条问题按「契约、一致性、运维、成本」四组排好,评审时逐条过,比讨论「这个架构好不好」有效率得多。
上线后当验收项。 第 15.1 节的 SLO 与第 15.2 节的演练剧本,是把判据变成可执行的检查。判据写在文档里不算数,能在监控面板上看到才算。
判据也有失效的时候。如果某条判据在你的场景里明显不适用,把它改掉,但要在 ADR 里写清楚为什么——附录 B 提供了模板。
与卷二的关系
卷二结束在「一条链路能不能上线」。卷三从这里接手,问的是「几十条链路、几百个消费者、跨多个集群时,事件流本身怎么治理」。
卷二留下的四个缺口在这一卷展开:
| 卷二缺口 | 卷三对应章节 |
|---|---|
| 跨集群语义 | 第 6.3、13.2 章 |
| 业务幂等的容量模型 | 第 5.2、9.3 章 |
| 契约治理的组织方式 | 第 6 章、第 11 章 |
| 长尾故障的观测 | 第 10 章、第 15.2 章 |
卷二验收单里的判据,在卷三会变成架构设计的前置条件——比如「每个主题的 minISR 已确认」,在卷三里会升级成「跨集群两端都要确认,且切换时不能回退」。
换句话讲,卷二的验收清单可以直接当作卷三的设计输入:先确认底座可用,再讨论架构。反过来则不成立——一套在不可靠底座上画出来的事件架构,无论图多漂亮,都跑不起来。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。