他讓分散式系統成為一門科學,然後說大多數人的「理解」只是溫暖的模糊感

圖靈獎得主 Leslie Lamport 在訪談中分享了 Bakery 演算法、Paxos、拜占庭將軍問題、LaTeX 背後的故事,並直言:多數程式設計師的「理解」只是溫暖的模糊感,寫不出證明就代表你不懂。

他讓分散式系統成為一門科學,然後說大多數人的「理解」只是溫暖的模糊感

封面圖

本文整理自 Podcast 節目《The Peterman Pod》2026 年 2 月播出的單集。

{{< youtube U719vQz-WFs >}}

{{< spotify "episode/7JHYszhd5pB3WRpjRyQPDH" >}}

{{< apple-podcast "tw/podcast/turing-award-winner-on-thinking-clearly-paxos-vs-raft/id1777363835?i=1000751017469" >}}


從一個被退稿的 bug 開始

1972 年,一位數學博士讀到了一篇關於並行程式同步問題的論文。問題可以用一句話概括:怎麼讓多個程式共用一台印表機,又不會把彼此的內容印成一團亂?他覺得這個問題看起來不難,很快寫了一個簡潔的兩程序解法,投稿到《ACM 通訊》(CACM)。幾週後,編輯回了一封信,指出他程式裡的 bug。

這個人是萊斯利.蘭波特(Leslie Lamport),後來的圖靈獎得主,分散式系統領域最重要的奠基者之一。那個被退稿的 bug,成了他整個學術生涯的起點。

被退稿這件事對他產生了兩個效果。第一,他明白了並行程式比看起來難得多,你需要嚴格的正確性證明才能確信自己沒搞錯。第二,他很不服氣,決定要把這個問題徹底解決。結果就是 Bakery 演算法。靈感來自熟食店的取號機:每位顧客進門抓一張號碼牌,號碼最小的先服務。但在並行系統中沒有中央發號的機器,每個程序得自己選號碼。蘭波特設計了一套方法讓這件事行得通,而且他的方案有一個當時所有人都認為不可能的性質:它不需要原子操作。就算一個程序在另一個程序寫入記憶體的同時去讀取,讀到完全錯誤的值,演算法照樣能正確運作。

蘭波特把這個結果拿給同事 Anatol Holt 看,對方的反應是不相信。蘭波特在白板上寫了完整的證明,Holt 找不到破綻,回家之後還是堅持「一定哪裡搞錯了」。但他始終沒能找到錯誤。這就是並行程式的弔詭之處:結果正確到讓人無法相信。

與 Dijkstra 喝啤酒的下午

這個並行程式同步問題的原始版本,是艾茲赫爾.戴克斯特拉(Edsger Dijkstra)在 1965 年提出的。如果你不熟悉這個名字,你幾乎肯定每天都在用他的發明。你打開 Google Maps 查路線,背後的最短路徑計算用的就是 Dijkstra 演算法,他在 1956 年花了大約二十分鐘在咖啡廳想出來的。你寫的每一行程式碼之所以不用 GOTO 跳來跳去,是因為他在 1968 年寫了那篇著名的〈Go To Statement Considered Harmful〉,幾乎以一己之力推動了結構化程式設計的革命。你的作業系統能同時跑多個程式而不互相干擾,靠的是他發明的號誌(semaphore)機制。他在 1972 年就拿了圖靈獎,而蘭波特在訪談中明確表示,自己認為戴克斯特拉的那篇 1965 年論文標誌著並行計算理論的真正起點。戴克斯特拉是並行計算的開山祖師,第一個認真把程式結構化為多個半獨立任務、然後研究它們如何同步的人。

在提出 Bakery 演算法之前,蘭波特和戴克斯特拉已經有過一次重要的交集。戴克斯特拉和幾個學生寫了第一個並行垃圾回收演算法,蘭波特看了之後發現可以把 free list 直接整合進一般的資料結構中,省掉額外的同步處理。他覺得這是一個很簡單、很明顯的改進,就把想法寄了過去。沒想到下一版論文出來時,戴克斯特拉直接把他列為共同作者。蘭波特當時覺得戴克斯特拉太慷慨了,因為這想法對他來說真的太明顯了。多年後他才意識到,那個「很明顯」的想法對大多數人來說一點都不明顯,而戴克斯特拉正是因此對他刮目相看。戴克斯特拉後來曾評價蘭波特擁有「非凡的抽象能力」。

1976 年,蘭波特受邀到荷蘭待了一個月,每週有一個下午和戴克斯特拉碰面,一邊聊研究一邊喝啤酒。關於這段時光,蘭波特補充了一句讓人忍不住笑的話:他大概沒有真的喝醉,因為他還得開車來回。而且荷蘭啤酒的酒精濃度本來就不高。那段時間唯一正式發表的成果,是一個 Bakery 演算法的變體。

不過,蘭波特對自己的認知轉變,來得比這些成果晚得多。他說自己直到獲得圖靈獎之後,才真正理解自己成功的原因不是特別聰明,而是擁有抽象的天賦。心理學上有個現象:擅長某件事的人往往意識不到自己有多擅長,因為那件事對他們來說太簡單了。反過來,不擅長某件事的人反而會高估自己。蘭波特把這個觀察壓縮成一句話:笨蛋覺得自己聰明,因為他們笨到不知道自己不聰明。

狹義相對論教會他的事

蘭波特最被引用的論文是 1978 年的《Time, Clocks, and the Ordering of Events in a Distributed System》。起因很單純:有人寄給他一篇關於分散式資料庫的論文,裡面的同步方案有一個微妙的問題。系統確實會讓事件按照某個順序執行,但那個順序可能跟事件實際發生的順序不同。要解決這個問題,得先嚴格定義什麼叫做「之前發生」。在日常生活中這是直覺,但在分散式系統中一點都不是。

蘭波特之所以能看出問題的核心,是因為他碰巧熟悉狹義相對論。愛因斯坦在 1905 年發表相對論,幾年後有人把它重新表述為四維時空觀。在這個框架裡,「事件 A 在事件 B 之前發生」有一個精確的定義:從 A 發出的訊號能在 B 發生之前抵達 B 的位置,前提是這個訊號的速度不超過光速。蘭波特看到了直接的類比:在分散式系統中,把「光速」換成「訊息傳遞」就行了。事件 A 在事件 B 之前發生,意思是 A 產生的資訊有可能透過系統中實際傳送的訊息,在 B 發生前影響到 B。這個定義聽起來簡單,但它奠定了分散式系統作為一門科學的理論基礎。蘭波特自己也說,這是第一篇對分散式系統提出科學性結論的論文。

但蘭波特認為那篇論文中更重要的概念,其實是狀態機。他指出,任何分散式系統都可以用狀態機來理解和設計。狀態機有一個狀態,執行命令會改變狀態並產生輸出。要理解一個程式為什麼能產生正確結果,關鍵是找到一個「不變量」:一個在每個執行步驟都為真的條件,保證最終結果的正確性。這種不變量證明的複雜度是程序數量的平方,遠低於行為證明中指數級的序列組合。諷刺的是,關於狀態機的這部分完全被忽視了。蘭波特提到,他曾兩次跟人討論這篇論文,對方都說裡面沒有提到狀態機。他不得不回去重讀自己的論文,確認自己沒有發瘋。

拜占庭將軍的命名由來

Time, Clocks 那篇論文解決的是沒有故障情況下的分散式系統問題。但分散式系統的一個重要目的就是容錯:如果一台電腦壞了,其他電腦還能繼續運作。更棘手的是,壞掉的電腦不一定是直接停機,它可能傳送錯誤訊息,甚至像叛徒一樣故意搗亂。

蘭波特從最壞的情況出發:假設一個故障的程序可能做出任何行為。他設計了一個使用數位簽章的演算法來解決這個問題。有趣的是,他之所以知道數位簽章這個概念,純粹是因為 Whit Diffie 是他的朋友。有一次他們在咖啡廳聊天,Diffie 提到他們正在研究一個尚未解決的數位簽章問題。蘭波特說「這看起來不難」,然後真的在餐巾紙上寫出了第一個數位簽章演算法。雖然那個演算法在當時不實用(需要 128 位元來簽署 1 位元),但概念上是完整的。

蘭波特後來加入 SRI,發現那裡的人也在解決類似的問題,但他們的方案不使用數位簽章。沒有數位簽章的版本需要四台電腦才能容忍一個故障,有簽章的版本只需要三台。一位波音工程師後來讀到這個結論時的反應是:「該死,我們需要四台電腦。」背後的脈絡是,1970 年代的石油危機讓航空公司急著打造更省油的飛機,而縮小控制面能省油但會讓飛機在空氣動力學上不穩定。只有電腦能快到足以即時修正,所以飛機的未來注定要由電腦來飛。能容忍一台電腦故障這件事,直接攸關乘客的性命。

蘭波特意識到這個結果需要被廣為人知,而他從戴克斯特拉那裡學到了一件事:一個好的故事能讓技術問題流傳得更廣。戴克斯特拉的「哲學家用餐問題」之所以出名,不是因為問題本身特別重要,而是因為那個幾位哲學家圍著桌子搶叉子吃義大利麵的故事很有畫面感。於是蘭波特也為自己的問題編了一個故事:幾位將軍要決定是否進攻,但其中可能有叛徒。他最初想到的是「阿爾巴尼亞將軍」,因為當時的阿爾巴尼亞是個對外界幾乎完全封閉的共產政權。但他的上司提醒他,世界上真的有阿爾巴尼亞人,用這個名字不太恰當。蘭波特轉念一想:拜占庭帝國已經不存在了,不會有人被冒犯。於是「拜占庭將軍問題」就此誕生,成為電腦科學史上最著名的問題命名之一。

Paxos vs Raft:「理解」到底是什麼意思

Paxos 是蘭波特最著名的演算法,解決的問題跟拜占庭將軍一脈相承:如何建構容錯的分散式系統。差別在於,業界關心的故障模式通常是電腦直接停機,而不是做出任意行為。

蘭波特發明 Paxos 的過程本身就是個好故事。他當時在 DEC 的研究實驗室,同事們建構了早期的分散式作業系統,所有電腦共用儲存空間。蘭波特覺得他們維持資料一致性的做法可能有問題,決定去證明這件事不可能做到。他開始推導:一個正確的演算法必須先做到 A,為了做到 A 又必須做到 B,為了做到 B 又必須做到 C。推到某個時刻他停下來,發現自己手上的不是不可能性證明,而是一個能解決問題的演算法。

但這個演算法從發明到正式發表,中間隔了八年。最初的審稿人認為論文還行但不太重要。幸好巴特勒.蘭普森(Butler Lampson)看出了它的價值。蘭普森是 Xerox PARC 的核心人物,後來也得了圖靈獎。他開始四處推廣用 Paxos 和狀態機的思維來建構分散式系統。因為想法一直在圈子裡流傳,蘭波特也就不急著發表。直到換了一位新編輯,論文才終於刊出。蘭波特甚至穿著印第安納瓊斯風格的考古學家裝扮去做報告,因為論文是以一個虛構的古代文明寓言來包裝的。結果聽眾的反應是:講座可能還不錯,但沒人真正理解這個演算法有多重要。

多年後,Raft 演算法的作者們宣稱他們的方案比 Paxos 更容易理解。他們甚至做了對照實驗:一班學生學 Paxos,另一班學 Raft,結果學 Raft 的學生普遍表示自己理解得更好。蘭波特對此有一個尖銳的觀察:後來有人在 Raft 中發現了一個 bug 並修復了,但他相信學生們覺得「更容易理解」的那個版本,正是有 bug 的那一個。

這讓蘭波特開始思考「理解」這個詞到底意味著什麼。對他來說,理解意味著你能寫出一個正確性證明。但對大多數人來說,理解只是一種「溫暖的模糊感」(warm, fuzzy feeling)。Raft 的描述方式是先講正常運作、遇到故障再處理,這更符合程式設計師習慣的思考順序,所以讓人覺得親切。但蘭波特描述 Paxos 的方式是先從兩個 phase 的結構出發,這更能幫助你理解演算法為什麼正確。親切感跟正確性是兩回事。一個讓你覺得好懂的演算法,不一定是正確的演算法。

寫不下來,就代表你不懂

除了分散式系統的理論貢獻,蘭波特還有一個影響了整個學術界的副產品:LaTeX。故事很簡單,他要寫一本書,TeX 是當時唯一的選擇,但直接用 TeX 太痛苦了,需要大量巨集。他決定稍微多花一點力氣,把這些巨集整理成其他人也能用的東西。他之前用過一個叫 Scribe 的系統,核心理念是讓使用者描述文件的邏輯結構,排版交給系統處理。Scribe 的排版效果不好,但這個「抽象」的思路讓蘭波特很喜歡。寫作的重點是想法,不是字型。

但蘭波特在這場訪談中反覆強調的,不是 LaTeX 本身,而是「寫作」這件事對思考的重要性。他有一句話被分散式系統社群廣為流傳:「如果你覺得自己在思考,但沒有寫下來,你只是以為自己在思考。」他進一步解釋:如果你認為自己知道一件事,但不把它寫下來,你只是以為你知道。這不是文學修辭,而是從數十年的正確性證明經驗中提煉出的實戰教訓。

蘭波特體會最深的經歷,是嘗試在數學界推廣結構化證明。他在並行程式的正確性證明中發展出一套層次化方法:一個證明拆成一連串步驟,每個步驟都有自己的子證明,子證明可以是一段文字,也可以再拆成更小的步驟。每一步都明確說明它依賴哪些前提,如果推導不成立,你馬上知道哪裡出了問題。他把這套方法用在純數學定理上,發現效果很好,於是在一個大約二十位數學家的研討會上介紹了這種方法。

他們的反應讓蘭波特震驚:他們變得憤怒,他甚至覺得他們可能會動手打他。蘭波特認為這種非理性的反應來自恐懼。會後有人站起來說「我不想為電腦程式寫證明」,但蘭波特的重點從來不是電腦,只是一種組織思路的方式。真正讓數學家不舒服的,是這套方法會暴露出他們以為自己知道但其實沒有寫清楚的東西。寫下來之所以更費力,正是因為它逼你誠實面對自己推理中的漏洞。大約三分之一的論文存在錯誤,而這些錯誤的根源往往就是覺得某個步驟「很明顯」所以跳過了。

我的觀察:抽象是天賦,寫作是方法

蘭波特在訪談最後被問到,如果能回到大學剛畢業時給自己一個建議,會說什麼。他的回答完全符合一貫的風格:「我很早就學到一件事,不要浪費時間回答你不需要回答的問題。我不會去想自己當初應該做什麼,因為那是一個我不需要回答的問題。」

這場訪談中讓我印象最深的,不是任何單一的技術貢獻,而是蘭波特對「理解」這個概念長達五十年的堅持。他反覆遇到同一個問題:人們以為自己理解了,但其實只是有一種感覺。Raft 比 Paxos 更好懂,但有 bug 的版本才是讓人覺得好懂的那一個。數學家覺得自己的證明沒問題,但被要求寫清楚每一步時就暴跳如雷。工程師覺得自己的系統是正確的,但他們只有程式碼,沒有演算法。

蘭波特對此開出的藥方始終如一:把它寫下來。不是寫程式碼,而是寫演算法。不是寫虛擬碼,而是寫數學。不是寫摘要,而是寫證明。他花了職業生涯後半段的大量時間,說服建構並行系統的人不要只寫程式碼,而是先把同步的核心邏輯抽象成演算法,然後再去實作。因為程式碼會把太多跟並行性無關的細節混在一起,讓你看不清真正重要的東西。

蘭波特認為狀態機就是並行計算的「圖靈機」。圖靈機捕捉了「什麼是可計算的」,而狀態機提供了一個足夠抽象、足夠強大的框架,能用數學語言描述任何你需要理解的並行系統。他直言,電腦科學家和程式設計師太沉迷於語言了。他們發明各種語言,以為語言能改善思考。蘭波特不同意。語言有它的用途,比如執行效率。但在「理解」這件事上,數學是無可取代的。

這個立場在今天看來可能有點不合時宜。軟體工程的趨勢是降低門檻,讓更多人能參與。蘭波特的方法論則是反過來的:他要求你提高自己的標準,用更嚴格的方式思考,承認你可能不像自己以為的那樣理解你正在做的事。在 AI 產生程式碼的時代,這種要求可能聽起來過時了。但也許正因為 AI 能幫你寫程式碼,理解程式碼在做什麼這件事變得更重要,而不是更不重要。蘭波特用一生的工作示範了一件事:抽象不是讓事情變得更複雜,而是讓事情變得更簡單。無限大不是比有限大更難,是更容易。用整數做算術比用 32 位元整數做算術簡單得多。這個反直覺的洞見,或許是他留給所有工程師最深刻的一課。