IT 论文精读 · PAPER 31

Time, Clocks, and the Ordering of Events(逻辑时钟)

Leslie Lamport · Massachusetts Computer Associates · CACM 1978

EN →

这篇论文干了什么?

1978 年,Leslie Lamport 提出了一个后来无处不在的想法:在一堆各自为政的电脑组成的系统里,怎么说清「哪件事先发生、哪件事后发生」。今天你转一笔账、发一条消息,背后往往是好几台机器在一起干活;它们必须对「谁先谁后」达成一致,否则账就对不上。Lamport 给了第一个干净的答案,这篇论文也成了整个分布式系统领域的思想原点。

先说个日常难题

你和朋友在两个城市,各看各的手表,可两块表并不完全对得准,还会越走越偏。现在要判断「你早上寄出的信」和「朋友那边发生的某件事」谁先谁后——光比两块表根本靠不住。多台电脑之间正是这样:每台有自己的石英钟、都会漂移,网络传消息又快慢不定。没有一块「大家都信的表」,先后就成了难题。

那个点子

Lamport 的巧思是:别去比表,去看「谁能影响谁」。关键抓手是消息——一条消息一定是先发出、才能被收到。于是只要 A 给 B 发了消息,就能笃定「A 那件事在 B 收到之前」。同一台机器上,先做的自然在先。把这些串起来,就得到一张「谁在谁之前」的关系网(这叫 happens-before,先于关系)。

妙的是:有些事彼此谁也影响不到(消息根本没传过去),那就干脆说它们「同时发生 / 并发」,不强分先后——这反而更诚实。

怎么让机器自动算出先后?

给每台机器发一个「号码牌」计数器(不是钟,就是个不断变大的号)。规则朴素到三句话:本地每做一件事,号 +1;发消息时把当前的号捎在信封上;收到消息时,把自己的号跳到「比信封上那个号还大」。

就像邮局盖邮戳:寄信盖一个号,收信方一看「哦这封是 7 号寄的」,就把自己的柜台号推到 8 往后接着走。这样一来,只要一件事能影响到另一件,它的号一定更小——号码牌就把「先后」自动排了出来。谁号小谁在前,万一撞号,就按机器编号定个先后当裁判。于是天各一方的机器,能排出一份人人都认、完全一样的顺序表。

这带来了什么?

有了这份统一的顺序表,就能让好几台互为备份的机器按同一个顺序处理同一批命令——同样的输入、同样的次序,各自算下来必然得到同样的结果,于是永远保持一致。这套「让多个副本步调一致」的配方,正是今天银行数据库、云存储、以及 Paxos、Raft 这些著名算法的共同祖师爷。一个 1978 年的计数器把戏,撑起了半个分布式系统世界。

说句诚实的:号码牌只保证「有影响的一定号更小」,但反过来不成立——两件事号有大小,未必真有先后,可能只是碰巧撞在一起、互不相干。想把这层也分清,得靠后来更重的「向量时钟」。

一句话记住

没有一块大家都信的表,就别比表——用「消息一定先发后收」定义先后,再给每台机器一个只增不减的号码牌,让有因果的事件号一定更小;补个平局裁判,天各一方的机器就能排出人人认同的同一份顺序,从而各自独立却始终一致。这是整个分布式一致性的思想原点。

想看时空图、逻辑时钟的更新规则和那个无中心互斥算法? → 切到精读版