建模的重要性:使用精確形式語言發現Paxos實現中的一個錯誤 - brooker

banq發表於2021-11-17

在過去的幾周裡,我一直在學習優秀的P 程式語言,一種用於建模和指定分散式系統的語言。我在 P 中做的第一件事就是實現 Paxos——一種我很熟悉的演算法,有很多微妙的失敗模式,而且很容易出錯。

為了測試 P 的模型檢查器,我特意按照Paxos Made Simple 中的描述實現了一個有缺陷的 Paxos 版本,模型檢查器發現Paxos實現出現錯誤。

我向一位同事提到了這一點,他說他們從未聽說過這個錯誤。我認為它應該更廣為人知,所以我想我應該寫下來:

問題不在於Paxos演算法本身,而在於論文中的描述。Michael Deardeuff 向我指出了這個錯誤,並將它寫在可能是有史以來最好的 Stack Overflow問答中 

事實證明這是因為 Paxos Made Simple 的文字中有兩個歧義。首先,關於接受(第二)階段的接受者的選擇(來自 Paxos Made Simple):

如果提議者從大多數接受者那裡收到對其準備請求(編號為 n)的響應,那麼它會向這些接受者中的每一個傳送接受請求,以獲得編號為 n 且值為 v 的提議,其中 v 是最高的值 -在響應中編號的提案,或者如果響應沒有報告提案,則為任何值。

如果您按照本宣告的內容,將接受訊息傳送給響應您的第一階段訊息的接受者,那麼問題就不會發生。不幸的是,這也使得演算法在實踐中不太穩健。幸運的是,還有另一種可能的修復方法。再次,來自Michael的回答:

通過接受一個值,該節點還承諾不接受較早的值。

Lamport 在 Paxos Made Simple 中沒有這麼說。相反,他說:

如果接受者收到對編號為 n 的提案的接受請求,則它接受該提案,除非它已經響應了編號大於 n 的準備請求。

 

Leslie Lamport 是我的技術寫作英雄之一。我重讀了他的一些論文,比如時間邏輯有什麼好處?有時只是因為我喜歡它們的書寫方式。指出這種歧義並不是批評他的寫作,而是提醒您即使在文字中對相對簡單的分散式協議進行清晰的描述也是多麼困難。正如蘭波特本人所說

散文不是精確描述演算法的方式。

這就是為什麼我如此喜歡 P 和 TLA+ 等語言的重要原因。它們不僅是指定、檢查和建模演算法的好方法,而且還是傳達它們的好方法。如果您使用分散式演算法,我強烈建議您選擇其中一種語言。

 

相關文章