1. 程式人生 > >Zookeeper——初識ZAB協議

Zookeeper——初識ZAB協議

對於使用過Zookeeper的開發人員來說,都應該對ZAB協議有所耳聞。它是為分散式協調服務Zookeeper專門設計的一種支援崩潰恢復的原子廣播協議,全稱是Zookeeper Atomic Broadcast(Zookeeper原子訊息廣播協議)。今天就介紹一下ZAB協議主要包括哪些內容,它是如何來實現來保證資料一致性的。

ZAB協議主要包括兩種基本的模式,訊息廣播和崩潰恢復。當整個服務框架在啟動的過程中或是當Leader伺服器出現中斷,退出,重啟等異常情況,ZAB協議就會進入恢復模式並選舉產生新的Leader伺服器。當選舉產生了新的Leader伺服器,同時叢集中已經有過半的機器與該Leader伺服器完成了資料同步之後,ZAB協議就會退出恢復模式,進入訊息廣播模式了。

訊息廣播

           類似於一個二階段提交協議,不同的是,它移除了中斷的邏輯處理。也就是說Follower伺服器要麼正常反饋Leader提出的事務,要麼就拋棄Leader伺服器。首先針對客戶端的事務請求,Leader伺服器會為其生成對應的事務Proposal,並將其廣播給所有的Follower伺服器,收集各自的選票,最後進行事務的提交。

這裡ZAB協議規定了,只要Leader伺服器收到了過半的Ack響應,就可以提交事務,並向所有的Follower伺服器傳送commit訊息,通知Follower伺服器進行事務提交。在訊息廣播的過程中,Leader伺服器會給Proposal分配一個全域性單調遞增的唯一ID,我們稱之為事務ID(ZXID

),由於ZAB協議需要保證每一個訊息的嚴格的因果關係,因此必須將每一個事務Proposal按照其ZXID的先後順序來進行排序與處理。在訊息廣播過程中,Leader伺服器會為每一個Follower伺服器分配一個單獨的佇列,然後將需要的廣播的事務Proposal依次放入到這些佇列中去,並且根據FIFO策略進行訊息傳送。每一個Follower伺服器在接收到這個事務Proposal之後,都會首先將其以事務日誌的形式寫入到本地磁碟中,並且在成功寫入後反饋給Leader伺服器一個Ack響應。當Leader伺服器收到過半的Ack響應後,就會先提交事務,接著傳送commit訊息給所有的Follower伺服器,Follower伺服器收到訊息後,也完成事務的提交。

崩潰恢復

           當我們的Leader伺服器在收到Ack訊息後,完成事務的提交,還沒來的及向Follower伺服器傳送commit訊息,就掛掉了,那麼整個叢集便會進入恢復模式,進行Leader選舉。ZAB協議規定了如果有事務在一臺伺服器上完成了提交,那麼它應該在所有的伺服器上都完成提交。另外如果Leader伺服器在接收事務後還沒來的及廣播就掛掉了,ZAB協議確保該事務被丟棄。基於這兩點,如果讓Leader選舉演算法能夠保證新選舉出來的Leader伺服器擁有叢集中所有機器最高編號(即ZXID最大)的事務Proposal,那麼就可以保證這個新選舉出來的Leader一定具有所有已經提交的事務。

           資料同步

完成Leader選舉之後,在正式開始工作之前,Leader伺服器會首先確認事務日誌中的所有Proposal是否都已經被叢集中過半的機器提交了,即是否完成資料同步。Leader伺服器需要確保所有的Follower伺服器能夠接受到每一條事務Proposal,並且能夠正確地將所有已經提交了的事務Proposal應用到記憶體資料庫中,Leader伺服器會為每一個Follower伺服器都準備一個佇列,並將那些沒有被各Follower伺服器同步的事務以Proposal訊息的形式逐個傳送給Follower伺服器,並在每一個Proposal訊息後面緊接著再發送一個Commit訊息,以表示該事務已經被提交。等到該Follower伺服器將所有其尚未同步的事務Proposal都從Leader伺服器上同步過來併成功應用到本地資料庫中後,Leader伺服器就會將該Follower伺服器加入到真正的可用Follower列表中,並開始之後的其他流程。

關於ZAB協議的主要內容就是以上這幾點,下面開始提出我的問題。

1.follower伺服器是如何感知當前leader伺服器是否正常工作?

Leader伺服器和Follower伺服器之間是通過心跳檢測機制來感知彼此的情況,如果Leader能夠在超時時間內正常收到心跳檢測,那麼Follower就會一直與該Leader保持連線。而如果在指定的超時時間內Leader無法從過半的Follower伺服器那裡收到心跳檢測,或者TCP連線本身斷開了,那麼Leader就會終止對當前週期的領導,並轉換到LOOKING狀態,所有的Follower也會選擇放棄這個Leader,同時轉換到LOOKING狀態。之後,所有程序就會開始新一輪的Leader選舉。

2.當Leader伺服器已經收到客戶端請求的事務,並已經廣播給所有的Follower伺服器,此時,在還未接收到過半的Ack訊息,Leader伺服器掛掉了,那麼該事務最終是會被丟棄還是被提交?

根據Leader選舉演算法,我們可以看出,各個伺服器會選舉出擁有ZXID最大的那個事務的伺服器作為Leader伺服器,只要該事務被提出,並且保證有Follower伺服器收到,那麼新選舉的Leader伺服器一定包含了這個事務,這個事務最終會被提交。

3.ZAB協議是如何處理那些需要被丟棄的事務Proposal的?

在ZAB協議的事務編號ZXID設計中,ZXID是一個64位的數字,其中低32位可以看作是一個簡單的單調遞增的計數器,針對客戶端的每一個事務請求,Leader伺服器在產生一個新的事務Proposal的時候,都會對該計數器進行加1操作,而高32位則代表了Leader週期epoch的編號,每當選擇產生一個新的Leader伺服器,就會從這個Leader伺服器上取出其本地日誌中最大事務Proposal的ZXID,並從該ZXID中解析出對應的epoch值,然後再對其進行加1的操作,之後就會以此編號作為新的epoch,並將低32位置0來開始生成新的ZXID。ZAB協議中的這一通過epoch編號來區分Leader週期變化的策略,能夠有效地避免不同的Leader伺服器錯誤地使用相同的ZXID編號提出不一樣的事務Proposal的異常情況。當一個包含了上一個Leader週期中尚未提交過的事務Proposal的伺服器啟動時,其肯定無法成為Leader,因為當前叢集中一定包含一個Quorum集合,該集合中的機器一定包含了更高epoch的事務Proposal,因此這臺機器的事務Proposal肯定不是最高,也就無法成為Leader了。當這臺機器加入到叢集中,以Follower角色連線上Leader伺服器之後,Leader伺服器會根據自己伺服器上最後被提交的Proposal來和Follower伺服器的Proposal進行比對,比對的結果當然是Leader會要求Follower進行一個回退操作,回退到一個確定已經被叢集中過半機器提交的最新的事務Proposal。