一致性、分布式事务与消息异步
0. 元信息
- 主题路径:
docs/topics/system-design/subtopics/consistency-and-messaging/README.md - 父主题:
system-design - 主分类:工程技术
- 辅助分类:计算机基础
- 适合对象:理解事务隔离级别、写过消息生产者/消费者的工程师
- 建议周期:1~2 周(每周 8~10 小时,重点是 Saga 编排代码与 Outbox 投递演练)
- 前置知识:
capacity-and-architecture、caching-and-data-layer;熟悉至少一种消息系统 - 最终目标:能用 CAP / PACELC 矩阵为订单 / 库存 / feed 选对一致性级别;能写 Saga 编排代码、Outbox 投递、Kafka 生产/消费,并解释为什么不丢消息
1. 学习路线
CAP 定理 + PACELC 扩展
→ 一致性级别(线性 / 顺序 / 因果 / 最终)
→ 分布式事务(2PC / 3PC / XA)
→ Saga 模式(Orchestration / Choreography)
→ Outbox 模式与 CDC(Debezium / Canal)
→ 消息系统(Kafka / RabbitMQ / Pulsar / NATS)
→ 事件溯源(Event Sourcing)与 CQRS
→ 死信队列与重试
→ 幂等设计(Idempotency Key / 唯一索引 / 状态机)
每一步都落到一个具体业务(订单 / 库存 / feed),写代码 + 跑故障注入。
2. 阶段周数分配
精简子主题不固定周数。按 §3 顺序完成。
3. 九阶段表
| 阶段 | 核心知识 | 实践产出 | 学会标准 |
|---|---|---|---|
| 1 | CAP / PACELC | 一致性矩阵 | 能为订单 / 库存 / feed 选对级别 |
| 2 | 一致性级别 | Quorum / 读修复 | 能用 N / R / W 推导可用性 |
| 3 | 2PC / XA | 失败演练 | 能解释阻塞 / 脑裂 / 协调者挂 |
| 4 | Saga 编排 | 编排代码 | 能画状态机 + 写补偿 |
| 5 | Saga 编舞 | 事件链 | 能解释为什么少用中央协调 |
| 6 | Outbox + CDC | 投递代码 | 能解释为什么不丢消息 |
| 7 | Kafka / RabbitMQ | 生产/消费代码 | 能解释 partition 与顺序 |
| 8 | 事件溯源 / CQRS | 物化视图 | 能解释审计与重放 |
| 9 | 幂等与死信 | 幂等代码 + DLQ | 能解释「至少一次」与「恰好一次」 |
4. 第一周任务
精简版省略固定日程。先完成阶段 1~4:CAP 矩阵 + 一致性级别 + 2PC 失败演练 + Saga 编排最小可用版本。
5. 阶段通用验收
精简版省略;每个产出保留状态机图、代码、故障注入记录、版本。
6. 最终验收
精简版省略;以 §3 第 9 阶段和 §9.4 问题口述检查为准。
7. 综合项目
精简版省略;成果并入父主题秒杀系统(库存预热 + Redis 原子扣减 + 异步下单 + 消息驱动)。
本主题贡献
- 在父主题
system-design的综合项目「秒杀系统」中,本主题(一致性、分布式事务与消息异步)负责 库存预热 + Redis 原子扣减 + 异步下单 + 消息驱动:用 CAP / PACELC 矩阵选对一致性级别,用 Saga 编排 / 编舞 + Outbox + CDC 把「下单 → 库存 → 支付 → 发货」串起来,并保证消息 at-least-once。 - 工程动作:用 Redis
DECR+ Lua 脚本做原子库存扣减(含失败时的回补两段式);用 Kafka 3.x 的 partition key =order_id保序;用 Debezium 把 Outbox 表变更 CDC 到 Kafka;用 Saga 编排代码(Camunda / Temporal 或 Python state machine)演示「下单扣库存 → 失败 → 补偿回滚 → 失败入 DLQ」;用 Idempotency Key + 唯一索引实现「至少一次」语义下的幂等。 - 与 system-design 其它子主题对接:把 CAP 矩阵给 caching-and-data-layer 决定 Redis 与 DB 的最终一致;把 Outbox + CDC 给 reliability-and-observability 接 DLQ 与
kafka.consumer.lag指标;给 capacity-and-architecture 提供 MQ 入口规格。
交付物清单:
consistency/cap_matrix.md:订单 CP / 秒杀库存 AP + Outbox / feed 最终一致 三档决策表 + 真实组件选型;saga/order_saga.{py|go|java}:编排式 Saga 完整可跑,含状态机 + 补偿动作(含补偿也挂的兜底);outbox/:业务表 + outbox 表 + Debezium 配置 + 投递 SQL;以及 CDC 断网演练恢复后至少一次 (at-least-once) 不丢的证据,含 offset 与 outbox 状态对照;mq/kafka_idem.{py|go|java}+bench/idempotent.md:Kafka 生产消费 + Idempotency Key + 死信 DLQ,含 partition rebalance 时 ≥ 1 次不丢的证据。
验收标准:
- 抢购 100 QPS 跑 5 分钟,超卖 = 0(库存表与出库流水完全一致);
- CDC 断网 60 s 后恢复,未投递消息数 = 0;至少一次 (at-least-once) 证据含 offset 与 outbox 状态对照;
- Saga 补偿失败入 DLQ + 监控告警,30 分钟内人工接管 ≥ 1 次演练成功;
- Kafka 在 partition rebalance 时
consumer.lag = 0且无重复业务执行(唯一索引验证)。
8. 推荐资料
精简版省略;使用 §9.3 和 §9.6 Source。
9. 学习资料汇聚(v0.3 自包含)
9.1 背景与动机
2000 年 Eric Brewer 在 PODC keynote 提出 CAP 猜想,2002 年 Gilbert 和 Lynch 给证明。12 年后 Brewer 自己重写「CAP Twelve Years Later」并提出 PACELC,修正了”三选二”误读。Amazon 2007 年披露 Dynamo,把最终一致 + Quorum + 读修复写进工业实践。Google 2012 年 Spanner 用 TrueTime + 2PC 实现全球强一致,把分布式事务推到工程极限。
事务模式上,1987 年 Garcia-Molina 和 Salem 在 PODS 提 Saga;2007 年 Pat Helland 在「Life Beyond Distributed Transactions」里把消息驱动的事务写进工业界。2014~2018 年 CQRS / Event Sourcing 在微服务浪潮中复活。Kafka 2011 年开源后成为事实标准消息总线,今天几乎所有「跨服务异步」都跑在它上面。
9.2 概念地图
flowchart TB
CAP[CAP / PACELC] --> Level[一致性级别]
Level --> Strong[线性/顺序一致]
Level --> Causal[因果一致]
Level --> Eventual[最终一致]
Strong --> Spanner[Spanner/CockroachDB]
Eventual --> Dynamo[Dynamo/Cassandra]
TX[分布式事务] --> TwoPC[2PC/XA]
TX --> Saga[Saga]
Saga --> Orchestration[编排]
Saga --> Choreography[编舞]
Saga --> Outbox[Outbox + CDC]
MQ[消息与异步] --> Kafka[Kafka/RabbitMQ]
Kafka --> Idempotent[幂等设计]
Kafka --> DLQ[死信队列]
CQRS[CQRS + Event Sourcing] --> Audit[审计与重放]
CQRS --> Read[读模型物化]
关系说明:CAP 决定业务可走强一致还是最终一致;事务模式解决跨服务一致;消息系统是 Saga 与事件溯源的血脉;幂等与死信是「消息可靠」的最后一道关。
9.3 基础知识讲解
9.3.1 论文 / 规范
- Eric Brewer, CAP Twelve Years Later(InfoQ 2012)。
- Gilbert & Lynch, Brewer’s Conjecture and the Feasibility of Consistent, Available, Partition-tolerant Web Services(2002)。
- Werner Vogels, Eventually Consistent(CACM 2008)。
- DeCandia et al., Dynamo: Amazon’s Highly Available Key-value Store(SOSP 2007)。
- Garcia-Molina & Salem, Sagas(PODS 1987)。
- Pat Helland, Life Beyond Distributed Transactions(2007)。
- Corbett et al., Spanner(OSDI 2012)。
- Greg Young, CQRS Documents(2010)。
- Kafka: Kafka: a Distributed Messaging System for Log Processing(NetDB 2011)。
- RabbitMQ AMQP 0-9-1 规范。
9.3.2 书
- Martin Kleppmann, Designing Data-Intensive Applications(2017)第 7~9 章。
- Chris Richardson, Microservices Patterns(Manning, 2018)第 3~4 章。
- Hughbert, Kafka: The Definitive Guide(2nd ed., O’Reilly 2021)。
- Kleppmann, Making Sense of Stream Processing(O’Reilly 2016)。
- Sam Newman, Building Microservices(2nd ed., 2021)。
9.3.3 博客 / 文档
- Apache Kafka 文档。
- RabbitMQ 文档。
- Debezium 文档。
- Uber: Schemaless / Domain-Oriented Microservice。
- InfoQ: Saga Patterns。
- Chris Richardson 官网:模式目录。
- Martin Fowler: Event Sourcing。
9.3.4 人物
- Eric Brewer:CAP / PACELC。
- Werner Vogels:Amazon CTO,最终一致。
- Pat Helland:Saga、消息。
- Greg Young:CQRS / Event Sourcing。
- Chris Richardson:Microservices Patterns。
- Martin Kleppmann:DDIA。
- Jay Kreps:Kafka 联合作者。
- Neha Narkhede:Kafka 联合作者,Confluent CTO。
9.3.5 方法
- CAP 决策表:每个业务先选 CP / AP / 选一致(默认)。
- Saga 编排 vs 编舞:单团队优先编排;多团队优先编舞。
- Outbox 模式:业务表 + outbox 表 + CDC 投递 = 原子 + 至少一次。
- Idempotency Key:所有写操作考虑幂等,重试不会爆。
- 死信队列:所有消费失败先入 DLQ,再人工 / 异步处理。
- 顺序保证:partition 内才保序,key 选业务主键。
- 物化视图:CQRS 写一份「读专用」表,绕过跨表 JOIN。
9.4 经典问题与经典案例
| 问题 | 为什么重要 | 最简答案 |
|---|---|---|
| 订单应该 CP 还是 AP | 业务边界 | 订单 CP;秒杀库存 AP + Outbox |
| 一致性级别怎么选 | 强一致 vs 最终一致 | 强一致代价高,最终一致要可补偿 |
| 2PC 为什么少用 | 协调者挂会阻塞 | 用 Saga + Outbox 替代 |
| Saga 编排 vs 编舞 | 协调方不同 | 单团队选编排;多团队选编舞 |
| Outbox 为什么可靠 | 单库事务原子 | 业务表 + outbox 表同事务;CDC 投递 |
| 消息为什么会丢 | 异步语义不清 | 至少一次 + 幂等 + 死信 |
| 消息为什么会重 | 至少一次语义 | Idempotency Key / 唯一索引 / 状态机 |
| 死信队列怎么用 | 消费失败兜底 | 失败入 DLQ;监控 DLQ 长度;告警 |
| Kafka partition 与顺序 | 业务顺序保证 | key 选业务主键;partition 数 ≥ 最大并发 |
| 事件溯源如何重放 | 状态修复与审计 | 物化视图 + 快照 + 按时间戳回放 |
| 幂等怎么实现 | 重试安全 | 数据库唯一索引 / 状态机 / 业务键 |
| Saga 补偿失败怎么办 | 补偿也挂 | 幂等 + 重试 + 死信 + 人工介入 |
9.5 学习难点
- 概念难点:CAP “三选二”误读。卡点来自把它当菜单;用 PACELC 与业务矩阵(订单 / 库存 / feed)做对照实验。
- 思维难点:消息为什么可能丢。卡点来自「异步就一定丢」的直觉;用至少一次 + 幂等 + 死信三件套把消息变成可补偿的。
- 工程难点:Saga 补偿失败。卡点来自把补偿当业务处理;补偿也需要幂等 + 重试 + 死信 + 人工兜底。
9.6 技术标准与接口
9.6.1 Entity
| 名称 | 版本 | 组织 | 状态 / 可访问性 |
|---|---|---|---|
| CAP 定理 | Gilbert-Lynch 2002 | PODC / IEEE | 经典定理;论文公开 |
| PACELC | Brewer 2012 | InfoQ | 扩展框架;公开 |
| Saga | Garcia-Molina & Salem 1987 | PODS | 经典论文;公开 |
| Outbox 模式 | 工业实践 | — | 模式;公开 |
| CQRS | Greg Young 2010 | CQRS 社区 | 模式;公开 |
| Event Sourcing | Fowler 2005 | martinfowler.com | 模式;公开 |
| Apache Kafka | 3.x | Apache | GA;Apache-2.0 |
| RabbitMQ | 3.x | Pivotal / VMware | GA;Apache-2.0 |
| Debezium | 2.x | Red Hat / 社区 | GA;Apache-2.0 |
| Apache Pulsar | 3.x | Apache | GA;Apache-2.0 |
| NATS | 2.x | Synadia | GA;Apache-2.0 |
9.6.2 Scope
- CAP / PACELC 是理论边界。
- Saga / Outbox / CDC 是跨服务事务模式,不替代单库事务。
- 消息系统是 Saga 与事件溯源的血脉。
- 幂等是「消息可靠」的最后一道关。
- 死信是「消费失败」的兜底。
9.6.3 Structure
- CAP:P 必然发生 → CP 或 AP 选一个。
- 一致性级别:线性 > 顺序 > 因果 > 最终。
- Saga 编排:中央协调器管理状态机。
- Saga 编舞:事件驱动,参与方自治。
- Outbox:业务表 + outbox 表 + CDC 投递 = 原子。
- Kafka:Producer / Consumer / Consumer Group / Partition / Offset。
- 死信:失败入 DLQ,监控 + 告警 + 人工。
9.6.4 Ecosystem
- 消息:Kafka / RabbitMQ / Pulsar / NATS / Redis Streams。
- CDC:Debezium / Canal / Maxwell / Oracle GoldenGate。
- 协调器:Apache Airflow / Temporal / Cadence / Camunda(编排)。
- 监控:Kafka Manager / Burrow / Confluent Control Center / Redpanda Console。
9.6.5 Depth Tiers
| 层级 | 能力 | 一致性 / 消息主题可观察标准 |
|---|---|---|
| L0 | 知道存在 | 知道 CAP / Saga / Outbox / Kafka |
| L1 | 看得懂示例 | 能读 Saga 编排代码、Kafka 生产消费代码 |
| L2 | 能正确调用 | 能写 Saga 编排、Outbox 投递、Kafka 生产消费 |
| L3 | 能解释与排错 | 能为业务选对一致性级别,写消息不丢 |
| L4 | 能设计与扩展 | 能设计跨服务事务、设计事件溯源系统 |
本计划目标:L3。
9.6.6 Source
- Apache Kafka 文档。
- Debezium 文档。
- Eric Brewer: CAP Twelve Years Later。
- 引用快照:2026-07-30。
10. 常见误区
- 把 CAP 当”三选二”菜单
- 所有跨服务都上 2PC
- Saga 没用 Outbox 直接同步调用
- 消息只关心发送不关心幂等
- 死信队列从来不看
- Kafka 用 round-robin partition 导致乱序
- 把 Event Sourcing 当数据库用
- CQRS 写模型与读模型各写一套 SQL
- 异步场景承诺强一致
- 不做消息追踪(traceid 不进消息)
- 不做 DLQ 告警
- 补偿失败不报警。
11. 所有知识点分类(统一规则)
- 编程语言
- 数据结构与算法
- 计算机基础
- 工程技术
- Web 与后端
- 前端与客户端
- 数据与人工智能
- 项目与职业能力
- 安全与可靠性
本计划归属:工程技术 主 + 计算机基础 辅。