分布式系统与数据面
查看范围、前置与边界
第 1、2 章精读远程调用的状态与重试预算;第 6 章精读 MVCC,第 7、8 章选读;第 12 章做项目一,注入丢响应故障,证明副作用只发生一次。约 12–16 小时。
展开路线 →先快读第 1 章的失败分类,再精读第 3、9、10 章的分区、租约与观测;第 11 章写一份爆炸半径受控的演练剧本。约 10–14 小时。
展开路线 →精读第 3、4、5 章的复制拓扑、线性一致判定与 Raft,用第 6 章的 MVCC 解释可见性;第 13 章做项目二。约 16–20 小时。
展开路线 →一次工具调用离开本机之后,为什么会出现「超时了但已经成功」「重试一次扣了两次钱」「主库切换后刚写的记录不见了」「扩容之后 p99 反而更高」?这些问题不是名词不够多,而是失败模型、一致性契约和容量边界没有写清楚。
你能为一个远程调用写出超时、重试、幂等与背压的完整契约;能判断该选主从、多主还是无主;能读懂 Raft 的选举与提交;能用 MVCC 解释隔离级别;能把队列、缓存、CDN、锁、观测和容量串成一条可验证的数据面。
分布式系统最容易写成两本错的书。
第一本错在只讲名词:CAP、BASE、最终一致、服务网格、云原生、可观测性,每一页都有新词,合上书却画不出一条请求的路径,也解释不了一次重复扣款。第二本错在只讲协议:Paxos 的两个阶段、Raft 的五个状态、2PC 的投票与提交都写对了,但读者不知道这些协议在业务代码里对应哪一行,也不知道超时该设 200 ms 还是 2 s。
这本书想写第三本:从一次具体的工具调用出发,沿着请求、复制、事务、消息、缓存和观测一路走,每到一个概念都问三件事——它解决什么失败、代价是什么、怎么观测。 协议是骨架,失败是血肉,观测是证据。
这本书的位置
它不是《Linux 系统与内核》的续集,也不是微服务名词表。它假设你已经知道 TCP 三次握手、socket、epoll、HTTP、DNS、TLS 的基本工作方式;这些内容在 Linux 书第 4 篇 已经讲过,本书只引用、不重写。容器与 Kubernetes 的基础同理,见 Linux 书第 5 篇。
本书只写数据面:请求怎么发、失败怎么判、状态怎么复制、事务怎么提交、消息怎么投递、缓存怎么失效、锁怎么过期、指标怎么解释、容量怎么估。控制面(调度、编排、服务发现、配置下发)只在必要时出现,而且从不展开成产品手册。
┌──────────────────────────────────────────────┐
│ 一次工具调用的数据面(本书主线) │
└──────────────────────────────────────────────┘
客户端 接入层 服务层 状态层
┌────────┐ ┌────────┐ ┌────────────┐ ┌──────────────┐
│ 重试 │─────▶│ 限流 │───────▶│ RPC/事务 │───────▶│ 复制日志 │
│ 超时 │ │ 鉴权 │ │ 幂等键 │ │ 共识/选主 │
│ 幂等键 │ │ 路由 │ │ 背压 │ │ MVCC/队列 │
└────────┘ └────────┘ └────────────┘ └──────────────┘
│ │ │ │
└────────────────┴──────────────────┴─────────────────────┘
观测:trace / metrics / logs / replay
读这张图要抓住一个事实:同一份「一次调用」会在六个地方留下状态——客户端的内存、接入层的连接、服务端的请求上下文、数据库的事务、复制日志的位置、观测系统的 span。一次重复副作用,往往是其中两个状态对不上:客户端认为失败了,服务端已经提交了;服务端认为只执行了一次,复制日志里却有两条。
全书地图
| 篇 | 章 | 回答的问题 | 关键产物 |
|---|---|---|---|
| 第 1 篇 请求与失败 | 1–2 | 一次远程调用为什么会「未知」;超时、重试、幂等、背压怎么组合 | 远程调用契约、重试预算、幂等状态机 |
| 第 2 篇 复制与一致 | 3–5 | 数据放在几台机器上;读到旧值算不算错;共识到底保证什么 | 复制拓扑、一致性契约、Raft 检查表 |
| 第 3 篇 数据与消息 | 6–8 | 事务边界在哪;消息为什么重复;缓存为什么越缓存越旧 | MVCC 读法、投递语义、缓存失效策略 |
| 第 4 篇 运行与治理 | 9–11 | 锁过期了怎么办;出事时看什么;容量和演练怎么做 | fencing token、观测面板、故障演练剧本 |
| 第 5 篇 项目 | 12–13 | 把前四篇压成两个能跑的服务 | 幂等工具调用后端、三节点复制 KV |
每一章都按同一个骨架写:先给一条真实请求或一次真实故障,再拆机制,再给边界与观测命令,最后落到「如果你来实现,必须回答哪些问题」。章末有 8–15 条陷阱清单和出口检查;陷阱不是「注意安全」这种空话,而是「把 Retry-After 当建议、把超时当失败、把 RPO=0 当默认」这类会直接导致事故的判断。
两个项目
纸上的协议必须落到进程上。第 12、13 章是两个可运行的项目,代码在 projects/:
- 项目一 · 幂等工具调用后端:HTTP + SQLite,带幂等键、请求指纹、租约、崩溃恢复、丢响应故障注入。你会亲手制造「服务端成功了,客户端超时了」,再用同一个键重试,证明副作用只发生一次。
- 项目二 · 小型复制 KV:三个 Python 进程,简化 Raft 选举与日志复制,支持线性一致读、租约读和陈旧读;用分区脚本把主节点隔离,观察旧主如何被 fencing 挡住。
两个项目都只用 Python 标准库,python3 -m unittest 可跑,故障注入脚本 bash -n 通过,且不依赖 Docker 或云账号。它们不是玩具:每个不变量都有对应的测试,每个测试都对应正文的一节。
不做什么
- 不重写 TCP/IP、socket、epoll、HTTP/DNS/TLS;这些在 Linux 书第 4 篇。
- 不重写容器、Kubernetes 基础与云原生编排;这些在 Linux 书第 5 篇。
- 不把 CAP 当口号。第 4 章会给出可判定的定义、反例和检查方法;只喊「三者选二」的段落不会出现。
- 不把分布式写成微服务名词表。每个名词必须能落到一条请求路径、一个状态字段或一条观测命令。
- 不复制母本原文、代码或图。所有图由本书自绘,所有代码为本书编写,公开案例只引用事实与链接。
本书的协议事实以 2026 年仍有效的规范与实现为准:Raft 以 Ongaro & Ousterhout 的论文与 etcd 3.5 的行为为参照;MVCC 以 PostgreSQL 16 与 InnoDB 8.0 为参照;对象存储以 S3 的强一致模型为参照。产品行为会变,书中凡是依赖版本的结论都标了版本;没有标版本的,按「截至 2026 年公开文档」理解。