文章很長,建議收藏起來,慢慢讀! 瘋狂創客圈爲小夥伴奉上如下珍貴的學習資源:html
高併發 必讀 的精彩博文 | |
---|---|
nacos 實戰(史上最全) | sentinel (史上最全+入門教程) |
Zookeeper 分佈式鎖 (圖解+秒懂+史上最全) | Webflux(史上最全) |
SpringCloud gateway (史上最全) | TCP/IP(圖解+秒懂+史上最全) |
10分鐘看懂, Java NIO 底層原理 | Feign原理 (圖解) |
更多精彩博文 ..... | 請參見【 瘋狂創客圈 高併發 總目錄 】 |
Paxos協議/算法是分佈式系統中比較重要的協議,它有多重要呢?java
大牛說:程序員
Google Chubby的做者Mike Burrows說過這個世界上只有一種一致性算法,那就是Paxos,其它的算法都是殘次品。面試
實際上:算法
理解了這兩個分佈式協議以後(Paxos/2PC),學習其餘分佈式協議會變得至關容易。sql
Paxos算法及變種算法在分佈式系統中應用普遍。
基於Paxos算法的變種有:ZAB、Raft。編程
Zookeeper 中的ZAB協議也是Paxos算法的變種。Zookeeper經過ZAB協議實現數據一致性,以提供數據一致性。設計模式
在分佈式系統中,節點之間主要使用消息投遞方式來完成。但經過消息投遞的方式會遇到不少意外的狀況,例如網絡問題、進程掛掉、機器掛掉、進程很慢沒有響應、進程重啓等狀況,這就會形成消息重複、一段時間內部不可達等現象。而 Paxos 算法就是基於消息傳遞且具備高度容錯特性的一致性算法。換句話說,Paxos算法的做用就是在可能發生這些異常狀況的分佈式系統中,快速且正確地在集羣內部對某個數據的值達成一致。安全
在各種介紹 Paxos 算法的文章中,都會提到著名的「拜占庭將軍問題」,以及偶爾也會提到的「兩軍問題」。關於這兩個問題的詳細介紹能夠閱讀這篇下面這篇文章,基本講清楚了。服務器
簡單的來講,拜占庭將軍問題描述了這樣一個場景:
拜占庭帝國有許多支軍隊,不一樣軍隊的將軍之間必須制訂一個統一的行動計劃,從而作出進攻或者撤退的決定,同時,各個將軍在地理上都是被分隔開來的,只能依靠軍隊的通信員來進行通信。然而,在全部的通信員中可能會存在叛徒,這些叛徒能夠任意篡改消息,從而達到欺騙將軍的目的。
這就是著名的「拜佔廷將軍問題」。從理論上來講,在分佈式計算領域,試圖在異步系統和不可靠的通道上來達到一致性狀態是不可能的。所以在對一致性的研究過程當中,每每假設信道是可靠的。事實上,大多數系統都是部署在同一個局域網中的,所以消息被篡改的狀況很是罕見;另外一方面,因爲硬件和網絡緣由而形成的消息不完整問題,只需一套簡單的校驗算法便可避免——所以,在實際工程實踐中,能夠假設不存在拜占庭問題,即假設全部消息都是完整的,沒有被篡改的。
拜占庭將軍問題是由 Paxos 算法做者萊斯利·蘭伯特提出的點對點通訊中的基本問題。該問題要說明的含義是,在不可靠信道上試圖經過消息傳遞的方式達到一致性是不可能的。
因此,Paxos 算法的前提是不存在拜占庭將軍問題,即信道是安全的、可靠的,集羣節點間傳遞的消息是不會被篡改的。
Paxos 算法是分佈式技術大師 Lamport 提出的。Lamport 爲了講述這個算法,假想了一個叫作 Paxos 的希臘城邦進行選舉的情景。這個算法也是所以而得名。在他的假想中,這個城邦要採用民主提議和投票的方式選出一個最終的決議,但因爲城的居民沒有人原意把所有時間和精力放在這種事情上,因此他們只能不定時的來參加提議,不定時來了解提議、投票進展,不定時的表達本身的投票意見。 Paxos 算法的目標就是讓他們按照少數服從多數的方式,最終達成一致意見。
規定一個提議包含兩個字段:[n, v],其中 n 爲序號(具備惟一性),v 爲提議值。
下圖演示了兩個 Proposer(提案者) 和三個 Acceptor(附議者) 的系統中運行該算法的初始過程,每一個 Proposer 都會向全部 Acceptor 發送提議請求。
當 Acceptor 接收到一個提議請求,包含的提議爲 [n1, v1],而且以前還未接收過提議請求,那麼發送一個提議響應,設置當前接收到的提議爲 [n1, v1],而且保證之後不會再接受序號小於 n1 的提議。
以下圖,Acceptor X 在收到 [n=2, v=8] 的提議請求時,因爲以前沒有接收過提議,所以就發送一個 [no previous] (尚無提案)的提議響應,而且設置當前接收到的提議爲 [n=2, v=8],而且保證之後不會再接受序號小於 2 的提議。其它的 Acceptor 相似。
若是 Acceptor 以前已經接收過提議 [n1, v1],如今接收到一個提議請求,提議爲 [n2, v2]。
若是 n1 > n2,那麼就丟棄該提議請求;
不然,發送提議響應,該提議響應包含以前已經接收過的提議 [n1, v1],設置當前接收到的提議爲 [n2, v2],而且保證之後不會再接受序號小於 n2 的提議。
以下圖:
Acceptor Z 收到 Proposer A 發來的 [n=2, v=8] 的提議請求,因爲以前已經接收過 [n=4, v=5] 的提議,而且 2 < 4, 所以就拋棄該提議請求;
Acceptor X 收到 Proposer B 發來的 [n=4, v=5] 的提議請求,由於以前接收到的提議爲 [n=2, v=8],而且 2 <= 4,所以就發送 [n=2, v=8] 的提議響應,設置當前接收到的提議爲 [n=4, v=5],而且保證之後不會再接受序號小於 4 的提議。
Acceptor Y 相似。
當一個 Proposer 接收到超過一半 Acceptor 的提議響應時,就能夠發送接受請求。
Proposer A 接收到兩個提議響應以後,就發送 [n=2, v=8] 接受請求。該接受請求會被全部 Acceptor 丟棄,由於此時全部 Acceptor 都保證不接受序號小於 4 的提議。
Proposer B 事後也收到了兩個提議響應,所以也開始發送接受請求。須要注意的是,接受請求的 v 須要取它收到的最大 v 值,也就是 8。所以它發送 [n=4, v=8] 的接受請求。
Acceptor 接收到接受請求時,若是序號大於等於該 Acceptor 承諾的最小序號,那麼就發送通知給全部的 Learner(學習者)。當 Learner 發現有大多數的 Acceptor 接收了某個提議,那麼該提議的提議值就被 Paxos 選擇出來。
Paxos 算法的一致性主要體如今如下幾點:
參考文獻:
《從Paxos到ZooKeeper》