面試官:能聊聊Paxos演算法和ZAB協議嗎

皮皮熊大白發表於2020-04-04

什麼是paxos演算法

是一種基於訊息傳遞的,具有高容錯的一致性演算法。

解決了什麼問題

主要解決分散式系統中,如何就某個決策達成一致性的問題。主要的工程實現,ZAB,Google Chubby、微信的 PhxPaxos。

paxos演算法與拜占庭將軍問題

paxos演算法的作者認為,在通道不可信的前提下,通過訊息傳遞的方式達成一致性,是不可能的。因此,paxos演算法的前提是不存在拜占庭將軍問題。也就是,認為通道是可信的,叢集間傳遞的訊息,不會被篡改。分散式系統中,各個節點訊息的傳遞方式有兩種,共享記憶體和訊息傳遞。paxos是基於訊息傳遞通訊模型。

paxos的三種角色

在paxos演算法中有三種角色,每種角色有不同的功能。但很多時候,一個程式可能充當多種角色。Proposal,提案;

  • Proposer:提案者
  • Accecptor:決策者
  • Learner:學習者,同步者

##paxos演算法的一致性 paxos演算法的一致性,通過以下幾點去保證:

  • 每個提案者在提案的時候,首先需要獲取一個全域性唯一,遞增的編號N,將N賦給提案。N的生成方式有兩種,全域性性生成器、提案者自身維護。
  • 每個表決者在接收到提案之後,會把提案編號儲存在本地。這樣每個表決者都有一個最大編號,假設是maxN。而每個表決者只會accept編號大於自己本地maxN的提案。
  • 最終只有一個提案被選定
  • 一旦一個提案被選定,那麼learner會同步該提案到本地。
  • 當然,沒有提案選出就不會有提案被選定

提交提案的兩種演算法

2PC和3PC演算法:

  • 2PC演算法:Tow Phase Commit 即,prepare->accept
  • 3PC演算法:Three Phase Commit 即,prepare->accept->commit

區別就是accept階段是否有commit功能。

3PC演算法描述

3PC演算法一共有三個階段,準備,接收,提交。

面試官:能聊聊Paxos演算法和ZAB協議嗎

prepare準備階段:

  • 提案者準備一個編號N的提議,然後向決策者傳送prepare(N),用於試探叢集是否支援該提案。
  • 每個決策者本地都有一個maxN,當接收到prepare(N)的時候,會與自己的maxN進行比較,有幾種情況。
    • 若N小於maxN,說明該提案已經過時,那麼就不回應或者回應error,來拒絕該提案。
    • 若N大於maxN,說明決策者可以接收該提案,會返回一個Proposal(myid,maxN,value),曾經接收的最大maxN的提案,來表示自己願意接收該提案。myid就是該提案者的id,maxN就是該提案的編號,value就是提案的值。如果是第一次接收,就都是null。

accept接收階段

  • 若提案者,接收到超過半數的反饋之後,那麼提案者就會把真正的提案Proposal(myid,N,value),傳送給所有的決策者。
  • 當決策者接收到提案之後,會再次與本地的maxN或者prepare記錄下的N,進行比較,若N大於等於該編號,那麼決策者就會accept該提案,並返回給提案者。否則,就會拒絕該提案
  • 若提案者沒有接收到超過半數決策的反饋的accept。那麼,要麼放棄提案,要麼遞增編號,重新提交請求,從prepare開始。

commit提交階段

若提案者接收到超過半數的反饋,就會向外傳送廣播資訊

  • 向accept的決策者傳送“可執行資料同步資訊”,讓決策者執行曾經接收到的提案。
  • 向未反饋的決策者,傳送“提案+可執行資訊”,讓他們接收到後馬上執行。

2PC演算法過程

2PC就是沒有提交過程,就是在prepare成功之後,會把真正的提交直接傳送給決策者,決策者接收到提案後會直接執行資料同步。不用等到commit訊息。2PC是有較多的弊端的,但是效率較高。

paxos演算法的活鎖問題

活鎖:活鎖就是一直重複嘗試-失敗-嘗試-失敗的過程,但是活鎖有可能自己解開。就是如果有很多提案一直提交,有可能某個提案一直失敗,一直遞增N,一直重試還是失敗,但是有可能某次就成功了。

#ZAB協議 ZAB:zookeeper Atomic Broadcast,zk原子性廣播協議。專門為zk設計的支援崩潰恢復的廣播協議,用來實現分散式系統中資料一致性。ZAB使用一個單一程式來處理所有的寫請求。當伺服器資料狀態放生變更了之後,叢集才用ZAB廣播協議,以事務提案Proposal的方式廣播給所有的副本。ZAB協議能夠保證一個全域性唯一遞增的xid。zk客戶端傳送讀請求的時候,如果接受者不是leader,那麼就會把請求轉發給leader,只有master能夠處理寫請求。

paxos和ZAB

ZAB是paxos的工業實現,目的是構建一個高可用的分散式資料主從系統,follower是leader的從機,leader掛了可以馬上從follower選一個leader。ZAB為了解決活鎖問題,只允許一個程式提交提案,屬於3PC提交。而,leader掛了時候選舉演算法是2PC,所有的follower都可以提交,就是我選我。

三種角色

  • leader:zk中寫請求的唯一處理者,也能處理讀請求。
  • follower:處理讀請求、對leader的提案進行表決、同步leader的結果、具有選舉權和被選舉權
  • observer:沒有表決權。只能處理寫請求、沒有選舉和被選舉權。 learner=follower+observer

三個資料

  • zxid:64位長度,高位32位是epoch,低32為xid
  • epoch:每個leader都有一個新的epoch,可以認為是年代?
  • xid:流水號。

三種模式

zk中有三種模式,沒有明顯的分界線,都交織在一起

  • 恢復模式:包含兩個重要階段,leader選舉和初始化同步
  • 廣播模式:包含兩類,初始化廣播和更新廣播
  • 同步模式:包含兩類,初始化同步和更新同步

同步模式

初始化同步:恢復模式中有兩個階段,leader選舉和初始化同步,當leader選出來之後只是一個準leader,只有經過初始化同步之後,才是一個真正的leader。 同步過程:

  • Leader為保證向每一個learner傳送的有序性,會為每一個learner準備一個對列。
  • Leader將那些沒有被learner同步到的事務封裝成proposal放入佇列。
  • Leader將proposal傳送給learner並加上commit訊息,表示事務已經提交,可以直接執行。
  • learner接收到訊息後,同步到本地
  • 向leader傳送ack訊息
  • Leader接收到ack訊息之後,會把learner加入到可用的follower列表會在observer列表。如果沒有返回ack或者ack沒有被leader收到,就不會加入到可用列表中。

訊息廣播演算法: 當leader完成同步之後,就進入正常的工作狀態,如果有寫請求,過來那麼leader會執行以下過程。

面試官:能聊聊Paxos演算法和ZAB協議嗎

  • leader接收到事務後,會為該事務生成一個全域性唯一的id,zxid,並且將事務封裝更一個Proposal。
  • Leader獲取到所有的follower列表,並通過每個follower的佇列,把proposal傳送給follower
  • follower接收到proposal之後會與自己本地已經儲存的最大zxid進行比較,如果當前的zxid較大,則把proposal儲存到本地日誌事務中,並返回ack
  • 當leader收到超過半數的ack之後,就會向所有的follower傳送commit訊息,把proposal傳送給observer。
  • 當follower接收到commit訊息之後,會把事務正式更新到本地。而observer接收到proposal會直接更新到本地。
  • follower和observer更新完訊息之後,就會向leader反饋ack。

四種狀態

每臺主機,在不同的節點會有不同的狀態

  • LOOKING:選舉狀態
  • FOLLOWER:follower正常的工作狀態
  • OBSERVERING:observer正常的工作狀態
  • LEADING:leader正常的工作狀態

observer數量問題

observer數量並不需要太多,雖然observer能夠在一定程度上提高系統的吞吐量,但是需要從leader同步資料。而Observer的同步時間是小於follower的同步時間的,當follower同步完成observer同步也就結束了,同步完成的observer會被加入到可用列表,而沒有同步完成的observer無法提高服務,就會造成資源浪費。

恢復模式的三個原則:

  • 主動讓出原則:若leader收到follower心跳的數量沒有過半,那麼leader會任務自己與叢集連線出現問題,會自動把自己的狀態改成LOOKING,重新去查詢leader。而去他的follower發現超過半數的主機任務失去leader,會重新進行選舉
  • 已處理的訊息不能丟:如果有的follower還沒收到commit訊息的時候leader掛了,那麼就會導致該事務有的server執行了有的沒有。當新的leader被選出,經過恢復模式後,就需要保證叢集中所有server執行了之前部分server執行的事務。
  • 被丟的訊息不能再現:當一個事務被通過,leader已經更新到本地了,但是還沒向follower傳送commit之前掛了。這臺機器再次成為follower的時候,本地上就會比其他機器多一個事務,是不行的。因此,類似這樣的事務是應該被丟棄的。而這種情況,服務端也不會向客戶端返回成功的訊息。

相關文章