分散式快照:Monkey-Lamport協議

banq發表於2024-06-16


這篇文章討論了Chandy-Lamport協議。這篇文章由Federico Ponzi於2024年5月30日釋出,並在2024年6月3日進行了最後更新。文章內容涵蓋了分散式快照試圖解決的問題、它的應用場景、系統模型、全域性狀態檢測演算法、快照一致性的定義、快照收集方法、實現該演算法的系統、TLA+規範以及結論和參考文獻。

關鍵點

  • 程序在收到第一個標記訊息時記錄其本地狀態。
  • 程序開始記錄來自通道的傳入訊息,直到在該通道上收到標記。
  • 記錄的訊息必須滿足兩個一致性條件才能形成有效的全域性快照:
    1. 如果記錄訊息為已接收,則也會記錄傳送事件。
    2. 如果某個程序記錄了訊息傳送事件,則該訊息不會被記錄為被其他程序接收。

1985年,當Alfrey-Lamport的分散式快照論文首次發表時,一些形式的分散式快照已經存在了一段時間。Lamport認為該協議Lamport時鐘基本思想的直接應用。除了回顧這篇論文,在這篇文章中,我還將展示一些真實的實現示例和協議的TLA+規範。

試圖解決什麼問題?
您需要記錄程式的全域性狀態。為什麼?因為,例如,你有一些複雜的計算正在進行中,你想知道已經到了哪一步。或者您有一個長時間執行的計算,並且您希望拍攝快照作為備份,以便在任何機器出現故障時從檢查點重新啟動計算,而不是從頭開始。

對於程式的狀態,我們引用區域性變數,通常引用程式所經歷的狀態歷史。

為什麼拍快照很難?首先,快照演算法不應該干擾正在執行的計算。

其次,如果你的程式是一臺機器上的一個程序,這很簡單!您可以建立一個API來表示“在5秒內記錄快照”或“每2小時”。對於在單機上執行的多執行緒/多程序程式,可以建立類似的API。

在分散式系統中,這個API不能工作,因為沒有全域性共享時鐘。您可能最終會得到不同步的快照,從而提供不一致的系統檢視。除了程序本身的狀態之外,我們還可以在快照中包含動態訊息。作為不一致快照的示例,程序B可以記錄它從A接收到訊息,而A的快照不包括該訊息被髮送到B。

這張紙有一個很好的視覺表現:想象你想拍一張充滿候鳥的天空的照片。一張照片是不夠的,你需要拍攝多張照片,並以一種提供一致景觀的方式將它們拼接在一起。這就是本文試圖解決的問題。


我們能用它做什麼?
更一般地,我們可以使用這樣的全域性狀態檢測演算法來驗證穩定性屬性。穩定性是單調的,如果它們現在保持不變,它們將永遠保持不變。例如,像“計算是否到達第n步”或“是否存在死鎖”這樣的屬性。


系統模型
系統由一組程序組成,這些程序之間使用通道進行通訊任何程序都有一個通往其他程序的“邏輯”通道。

假設通道:

  • 有無限的緩衝區,
  • 沒有錯誤,
  • 具有有限的遞送延遲,
  • 按傳送順序(FIFO順序)傳送訊息。

全域性狀態檢測演算法
執行是分散的,即,沒有協調快照的“主”程序,並且可以由任何程序啟動。同樣重要的是要注意,即使兩個程序在彼此不知道的情況下同時啟動快照協議,演算法也是正確的。

所提供的解決方案旨在僅解決此問題一次(拍攝一個快照)-將其擴充套件到多次執行應該是微不足道的。

該演算法的工作原理是透過通道傳送稱為“標記訊息”的特殊訊息。程序的行為會有所不同,具體取決於它們之前是否收到過標記訊息。這些標記訊息是演算法的一部分,而不是底層計算的一部分-它們不會出現在快照本身中。本質上,當程序透過通道接收到第一個標記訊息時,它將記錄自己的狀態並開始記錄來自所有通道的傳入訊息。它將停止記錄傳入的訊息從一個通道,只要它收到一個標記訊息透過那裡。

Chandy-Lamport 分散式快照演算法使用標記訊息來記錄跨程序的一致全域性狀態,而不會中斷底層計算。標記訊息的工作原理如下:

  • 任何程序都可以透過記錄自己的狀態並在其每個傳出通道上傳送標記訊息來啟動快照。
  • 當程序第一次收到標記訊息時:
    1. 它記錄其本地狀態。
    2. 它將標記到達的傳入通道的狀態記錄為空。
    3. 它向所有傳出通道(標記到達的通道除外)傳送標記訊息。
  • 如果程序在記錄其狀態之後但在接收所有傳入通道上的標記之前接收到常規訊息,它會將該訊息記錄為相應傳入通道狀態的一部分。
  • 一旦程序在其所有傳入通道上都收到標記,它就完成了記錄其本地快照。

關鍵點是:
  1. 標記訊息在系統中傳播,導致程序記錄其本地狀態。
  2. 在通道上的標記之前收到的訊息被記錄為該通道快照狀態的一部分。
  3. 在通道上的標記之後收到的訊息不屬於快照的一部分。

該演算法保證記錄的全域性快照遵循一致的切割規則,不會干擾程序的正常執行。

如果在 Chandy-Lamport 分散式快照演算法中標記訊息延遲,則不會影響記錄的全域性快照的正確性。這是因為該演算法依賴於程序間通訊通道的 FIFO(先進先出)排序特性。

當標記訊息延遲時會發生以下情況:

  1. 當一個程序啟動快照演算法時,它會記錄其本地狀態並在其所有傳出通道上傳送標記訊息。
  2. 如果標記訊息在通道上延遲,則常規應用程式訊息可能會在延遲標記之前到達接收程序。
  3. 接收過程將記錄延遲標記之前到達的所有應用程式訊息作為快照傳入通道狀態的一部分。
  4. 一旦延遲標記最終到達,接收過程就會根據演算法規則停止在該通道上記錄訊息。
  5. 延遲標記不會違反一致的全域性快照屬性,因為:
    • 任何記錄為已接收的訊息都意味著其傳送事件也被記錄(由於 FIFO 排序)。
    • 記錄的任何傳送事件都意味著該訊息不能被記錄為被其他人接收(由於 FIFO 排序)。
    <ul>
    因此,雖然延遲標記可能會導致在特定通道的狀態上記錄更多訊息,但它不會破壞全域性快照的一致性規則。

    FIFO 排序可確保儘管存在延遲,訊息仍能以正確的順序記錄。關鍵點在於,得益於 FIFO 通道假設,Chandy-Lamport 演算法可以容忍標記訊息傳播中的任意延遲,並且仍然可以捕獲一致的全域性快照。


    實現此演算法的系統
    這些系統已經實現了分散式快照並在其操作中使用它。
    Hazelcast Jet是一個分散式流處理器,它使用分散式快照來實現分散式計算的容錯。

    每隔一段時間,Jet就會升起一個全球標誌,上面寫著“是時候再拍一張快照了”。屬於源頂點的所有處理器觀察該標誌,儲存它們的狀態,向下遊處理器發出屏障項並恢復處理。
    資料來源:官方檔案檔案

    Apache Flink是一個流處理框架,它以兩種方式使用分散式快照:
    首先,它被用作全域性狀態的常規備份的檢查點。當應用程式失敗時,它用於恢復。其次,它用於死鎖檢測。當前程式在快照後繼續執行。然後,分析快照以檢視應用程式中是否存在死鎖狀態。如果是,將進行相應的處理。

    在Flink中,在快照協議結束時,快照收集器(中央伺服器)開始收集快照,以形成全域性一致性快照。

    TLA+規範
    提供了 TLA+ 規範,用於正式建模和驗證協議的正確性。

    可以在GitHub上檢視。

    結論
    在這篇文章中,我回顧了Alfrey-Lamport分散式快照協議論文,並介紹了我為它編寫的TLA+規範。這篇論文概括了為解決特定例項(如終止檢測)而編寫的更具體的演算法。穩定性屬性概括了諸如“此計算是否已終止”或“此計算是否處於死鎖狀態”之類的屬性。

    在分散式系統中拍攝全域性快照是很困難的,因為缺乏共享時鐘,打個比方,這就像試圖以一致的方式拼接天空的多張照片。

    分散式快照是一種在分散式系統中記錄程式全域性狀態的技術。它對於故障恢復、系統備份或檢測穩定性屬性等場景非常有用。Chandy-Lamport協議利用特殊的標記訊息在沒有全域性共享時鐘的分散式系統中實現快照,確保了快照的一致性。
     

    相關文章