unified - map

13. 大一统:十二个思想在四大件和技术栈里的复现总图

0. 本章先解决什么问题

前十二章每章追一个思想。本章做收拢:把十二个思想钉进一张总图,把它们之间的咬合线画出来,再用三个没讲过的新技术做落格练习,验证这张图真的能把”学一个新中间件”的成本从全量压到增量。

十二个思想总图

这张图怎么读

十二个格子分三行:存储侧、计算侧、分布式侧。每格写着思想名和两三个代表实例。所有格子共同的地基是三条硬件事实:延迟阶梯、顺序快于随机、传输按块。

1. 三条硬件事实:所有思想的共同地基

十二个思想没有一个是凭空聪明,全部是对三条物理现实的应对。成本模型 建立过这套语言,压缩成三行:

  1. 延迟阶梯: L1 约 1 ns,内存约 100 ns,SSD 约 100 us,
    跨机房毫秒级。相邻层差两三个数量级
  2. 顺序快于随机: 机械盘差数百倍,SSD 和内存(预取、缓存行)同样受益
  3. 按块传输且有固定成本: 磁盘按扇区,内存按缓存行,网络按报文,
    摊薄固定成本只能靠一次多带

对应关系一眼可辨:缓存和池化对付第 1 条,日志和不可变文件对付第 2 条,定长块和批处理对付第 3 条;分布式侧的四个思想对付的是第四条更狠的现实,跨机器之后消息会丢、会迟、会乱序,而机器本身会死。

2. 总表:十二章各自的一句话

#思想一句话内核本书章节代表实例
1事件驱动等待集中给内核,就绪才分发01epoll、Redis ae、Netty
2定长块按固定大小块分配搬运缓存0216 KB 页、4 KB 页、Kafka 段
3缓存分层小快存储挡大部分访问03buffer pool、Redis、CDN
4日志先行随机改写成顺序追加04redo、AOF、Kafka
5副本复制送日志到别处重放05binlog 复制、PSYNC、ISR
6多数派过半集合必有交集06Sentinel、Raft、MGR
7分片route(key) 决定数据去哪0716384 槽、分库分表、partition
8间接层名字和位置解耦08页表、DNS、代理、AOP
9池化复用贵的东西造好了别扔09线程池、HikariCP、内存池
10写时复制与多版本共享读,写时才付钱10fork、MVCC、COW List
11批处理攒一批摊固定成本11组提交、pipeline、攒批
12惰性与摊销大代价拆碎或推迟12渐进 rehash、过期删除

3. 思想不是并列的,是嵌套咬合的

总表容易给人”十二个独立工具”的错觉,实际它们咬得很紧。四条咬合线,每条都在前面的章节里出现过,这里连成网:

  • 日志线:日志(4)是复制(5)的载体,复制进度决定选主(6)里谁上位,
    选主的多数派同时保护复制的提交点(Raft 里两者共用一个过半),
    纪元编号再把旧主的日志封印
  • 块与缓存线:块(2)是缓存(3)的搬运单位,buffer pool 的脏页靠日志(4)兜底,
    刷脏是批处理(11),页的非原子写靠 doublewrite 补丁,
    删除的空间靠惰性(12)的 purge 慢慢收
  • 间接与分片线:分片(7)的槽位表是一层间接(8),
    间接层的翻译表本身是缓存(3),MOVED 就是缓存失效通知,
    smart client 的本地槽表又是池化(9)之外另一种”客户端持有资源”
  • 快照线:BGSAVE 的快照靠写时复制(10),fork 出来给复制(5)做全量,
    rehash(12)在快照期间提高扩容阈值以忌惮 COW 的内存账,
    AOF 重写(4)又用同一个 fork

所以拿到新系统时最有信息量的问题往往是跨格子的:它的日志同时用来做恢复和复制吗?它的间接层缓存在哪、怎么失效?它的摊销把尖刺转移给谁了?它的快照撞上写高峰会发生什么?

4. 第十三条线索:幂等与重试

有一条线索贯穿全书但没有自己的章节,在收尾处必须点破。第 5 章的复制可能重放、第 6 章的切换窗口可能重发、第 11 章的整批重试可能重复投递,它们把同一个问题推给了使用者:

消息可能重复到达,操作必须经得起重做。
TCP 用序号去重(协议层内置幂等)
MQ 的”至少一次”投递 + 消费端幂等(业务唯一键、去重表、
MQ高级 里的方案全在做这件事)
HTTP 的幂等方法约定(GET/PUT 幂等,POST 不幂等所以要防重提交)
支付系统的幂等号、上一章 JDBC 批量重试的插入冲突处理
第 6 章的 fencing token 也是它: 拒绝旧时代的重放

规律:分布式世界里”恰好一次”几乎总是”至少一次 + 幂等”拼出来的。看到任何重试逻辑,下一个问题永远是”重复了怎么办”。

5. 落格练习:三个没学过的系统

拿三个前面没展开的东西验证总图的可用性。

5.1 Elasticsearch

translog -> 日志先行(4)
倒排索引段不可变 + 段合并 -> 不可变文件(10) + 摊销(12)
refresh 攒一秒才可见 -> 批处理(11)
hash(_routing) % 主分片数 -> 分片(7)
primary/replica -> 复制(5)
master 节点选举 -> 多数派(6)
filesystem cache 依赖 -> 缓存(3)
真正要新学的增量: 倒排索引结构本身、打分、DSL

5.2 RocksDB / LevelDB

WAL + memtable -> 日志先行(4) + 批量刷盘(11)
SSTable 不可变 + compaction -> 不可变(10) + 摊销(12)
block cache + 定长 block -> 缓存(3) + 定长块(2)
布隆过滤器挡无效读 -> 第 3 章穿透方案的同款零件
真正要新学的增量: 层级 compaction 策略、读写空间放大的调参

5.3 etcd

Raft 日志 -> 日志(4) + 复制(5) + 多数派(6) 三合一
watch 机制 -> 事件驱动(1)
租约 lease 心跳 -> 第 6 章的判死机制
boltdb 的 B+ 树与页 -> 定长块(2)
MVCC 多版本键 -> 多版本(10)
真正要新学的增量: Raft 的工程细节(日志压缩、成员变更)

三个都没学过的系统,落完格七成机制是旧知识,剩下三成才要真花力气。这就是总图的用途:把新技术拆成”落在哪几格”加”真正新增的部分”,学习成本从全量变增量。

6. 怎么背这张图

不用背十二个名词,记三层结构就够:

底层: 三条硬件事实(延迟阶梯、顺序优先、按块有固定成本)
中层: 每条事实对应两三个应对套路
顶层: 每个套路在自己章节里有一个”参考实现”
(epoll、16 KB 页、buffer pool、redo、binlog 复制、
Sentinel、16384 槽、页表、ThreadPoolExecutor、
fork、组提交、渐进式 rehash)
从参考实现出发横向类比,比从定义出发背名词牢固得多

7. 学完本章你能解决什么问题

  1. 三条硬件事实分别催生了哪几个思想?
  2. 四条咬合线各自串起哪几章,为什么说思想是嵌套的?
  3. “恰好一次”在分布式里通常怎么拼出来?
  4. 拿到新中间件,落格的顺序和跨格问题清单是什么?
  5. ES 的 refresh、RocksDB 的 compaction、etcd 的 lease 各落在哪格?

核心一句话:硬件只有三条事实(外加分布式的”消息不可靠、机器会死”),应对只有十二个套路,产品是套路的排列组合;学新技术先落格,落不进去的部分才是真正的增量,而跨格的咬合处往往藏着系统最深的设计。

延伸阅读