专业书籍精读 · DDIA · 第 9 章

一致性与共识

Designing Data-Intensive Applications · Ch 9 · Martin Kleppmann · 2017

EN →

这一章讲什么?

你刷的每个大网站,背后都不是一台电脑,而是成百上千台机器一起干活。它们必须对一些「事实」达成一致:现在谁是主管(谁说了算)、这笔订单到底成没成、这个用户名是不是已经被占了。这一章讲的就是:一群各自可能宕机、消息可能丢的电脑,怎么可靠地「说到一块儿去」——这就是一致性共识

先打个比方

把这套系统想成一屋子人合用一个记事本,但每人手里其实是一份复印件。理想情况是:谁写一笔,所有人下一眼看到的都是同一个最新值,没人会读到旧的——这种「一堆复印件用起来就像只有一本」的效果,就是这章最重要的概念,叫线性一致。难点在于:复印件之间同步要时间,一不小心你翻到的就是别人三秒前的旧版本。

旧世界为什么难

如果电脑们各说各话,就会出乱子:两台机器都以为自己是主管(叫脑裂),一笔钱被扣两次;两个人同时抢到同一个用户名。更麻烦的是网络会断——一半机器忽然联系不上另一半,而且谁也分不清对方是真死了还是只是暂时失联。在这种半明半暗里还要做出统一决定,是分布式系统最难的地方。

核心诀窍:过半数投票

秘诀出奇地简单——投票,而且要过半数。想让大家认定一件事,就让超过一半的机器投票通过。为什么非得过半?因为任意两个「过半数」的人群一定有重叠的成员,于是不可能同时选出两个互相打架的结果——脑裂被从根上堵死。选主管是一次这样的投票;给事件排顺序也是——大家把发生的事按同一个顺序抄进一本共用的流水账,谁都不许插队,顺序自然就统一了。这套「靠过半数达成一致」的机制,就叫共识

该怎么用

好消息:这套东西极难写对,所以别自己造——现成的 ZooKeeper、etcd 这类「协调服务」已经把它封装好,选主、加锁、排顺序,直接调用就行。还要记住一条著名的取舍(叫 CAP):网络一旦断裂,「保持一致」和「保持可用」只能二选一。诚实地说,达成一致是有代价的——每件事都等过半数点头,天生比单机慢,这份「慢」买来的是「不会算错」。

一句话记住

一群会宕机、会失联的电脑要可靠地「达成一致」,靠的是过半数投票——它一口气解决了选主、排顺序、抢唯一名额。代价是更慢,且网络分裂时一致与可用二选一。别自己造,用 ZooKeeper / etcd。

想进到线性一致、全序广播、共识算法与 2PC 的具体机制? → 切到精读版