Zookeeper之數據同步原理

Zookeeper數據同步

zk通過三種不同的 集羣角色來組成整個高性能集羣,在zk中,客戶端會隨機連接到zk集羣中的一個節點,如果是讀請求,就直接從當前節點中讀取數據,如果是寫請求,那麼請求會被轉發給leader提交事務,然後leader會廣播事務,只要超過半數節點寫入成功,那麼寫請求就會被提交(類2PC事務,2PC是全數節點ok)

在這裏插入圖片描述

  • 問題:
    • 集羣的leader節點如何選舉出來?
    • leader節點崩潰以後,整個集羣無法處理寫請求,如何快速從其他節點裏面選出出新的leader呢?
    • 原leader節點臨時網絡故障,恢復後腦裂怎麼解決?
    • leader節點和各個follower節點的數據一致性如何保證?

一、ZAB協議

Zookeeper Atomic Broadcast,協議是爲分佈式協調服務 Zookeeper 專門設計的一種支持崩潰恢復的原子廣播協議。在 Zookeeper 中,主要依賴 ZAB 協議來實現分佈式數據一致性,基於該協議,Zookeeper 實現了一種主備模式的系統架構來保持集羣中各個副本之間的數據一致性。

1、介紹

包含兩種基本模式,分別是 崩潰恢復、原子廣播

​ 當整個集羣在啓動時,或者當leader 節點出現網絡中斷、崩潰等情況時,ZAB協議就會進入恢復模式並選舉產生新的leader,當leader服務器選舉出來後,並且集羣中有過半機器和該leader節點完成數據同步後(同步指得是數據同步,用來保證集羣中過半的機器能夠和leader服務器的數據狀態保持一致)。ZAB協議就會退出恢復模式。

​ 當集羣中已經有過半的Follower 節點完成了和Leader 狀態同步以後,那麼整個集羣就會進入消息廣播模式。整個時候,在Leader 節點正常工作時,啓動一臺新的服務器加入到集羣,那麼這個服務器就會直接進入數據恢復模式,和Leader 節點進行數據同步。同步完成後即可正常對外提供非事務請求的處理。

​ 需要注意的是:leader 節點可以處理事務請求和非事務請求,Follower 節點只能處理非事務請求,會把這個請求轉發給Leader服務器

2、消息廣播的實現原理

消息廣播的過程實際上是一個簡化版本的二階段提交過程(可以去了解2PC和3PC協議

// TODO 記得畫圖

流程如下:

  • 1、leader 接受到消息請求後,將消息賦予給一個全局唯一的64位自增id,叫:zxid,通過zxid的代銷比較即可以實現因果有序的這個特徵
  • 2、leader 爲每個follower 準備了一個FIFO隊列(通過TCP協議來實現,以實現了全局有序這個特點)將帶有zxid的消息作爲一個提案(proposal)分發給所有的follower
  • 3、當follower接受到proposal,先把proposal寫到磁盤,寫入成功以後再向leader恢復一個ack
  • 4、當leader 接受到合法數量(超過半數節點)的 ack,leader 就會向這些follower發送commit命令,同時會在本地執行該消息
  • 5、當follower接受到消息的commit命令以後,就會提交該消息

15875094712234

注意1: 和完整的2PC事務不一樣的地方在於,zab協議不能終止事務,follower節點要麼ack給leader,要麼拋棄leader,只需要保證過半數的節點響應這個消息並提交了即可,雖然在某一個時刻follower節點和leader節點的狀態不一致,但是也是這個特性提升了集羣的整體性能。當然這種數據不一致的問題,zab協議提供了一種恢復模式來進行數據恢復

注意2:leader的投票過程,不需要Observer 的ack,也就是Observer 不需要參與投票過程,但是Observer 必須要同步Leader 的數據從而在處理請求的時候保證數據的一致性

二、崩潰恢復原理

主要是Leader 節點崩潰 或由於 網絡問題導致 Leader服務器失去了過半的Follower節點的聯繫,那麼就會進入到崩潰恢復模式,這種模式下ZAB 需要做兩件事

  • 選舉出新的Leader
  • 數據同步

1、爲什麼有崩潰恢復模式

前面的指出消息廣播時,知道ZAB協議的消息廣播機制是簡化版的2PC協議,這種協議只需要集羣中過半的節點響應提交即可。但是它無法處理Leader 服務器崩潰帶來的數據不一致問題。因此在ZAB協議中添加了 “崩潰恢復模式” 來解決這個問題

2、崩潰恢復設計猜想

在ZAB協議中的崩潰恢復需要保證,如果一個事務Proposal 在一臺機器上被處理成功,那麼這個事物應該在所有機器上都被處理成功,哪怕是出現故障。爲了達到這個目的,我們先來設想一下,在zookeeper中會有哪些場景導致數據不一致,以及針對這個場景,zab協議中中的崩潰恢復咋處理

a、已經被處理的消息不能丟

當Leader 收到合法數量的 follower 的ACKs 後,就向各個follower 廣播 commit 命令,同時也會在本地執行commit 並向連接的客戶端返回[成功]。但是如果在各個follower 在收到commit 命令前leader 就掛了,導致剩下的服務器並沒有執行到這條消息

在這裏插入圖片描述

圖中的C2 就是一個典型的例子,在集羣正常運行過程的某一個時刻,Server1 是leader 服務器,先後廣播了消息P1、P2、C1、P3和C2。其中當leader 服務器把消息C2(Commit 事務 proposal2)發出後就立即崩潰退出了,那麼針對這種情況,ZAB協議就需要確保事務Proposal2 最終能夠在所有的服務器上都能被提交成功,否則將會出現不一致。

b、被丟棄的消息不能再次出現

在這裏插入圖片描述

當leader 接受到消息請求生成proposal 後就掛了,其他follower 並沒有收到此proposal ,因此經過恢復模式重新選了leader後,這條消息是被跳過的。此時,之前掛了的leader重新啓動並註冊成了follower,他保留了被跳過消息的proposal狀態,與整個系統的狀態是不一致的,需要將其刪除。

總結

ZAB協議需要滿足上面兩種情況,就必須要設計一個leader 選舉算法;能夠確保已經被leader提交的事務proposal 能夠提交、同時丟棄已經被跳過的事務 proposal 。針對這個要求

1、如果leader 選舉算法能夠保證新選舉出來的leader 服務器擁有集羣中所有機器最高編號(ZXID)的事務Proposal,那麼就可以保證這個新選舉出來的leader一定具有已經提交的提案。因爲所有提案被Commit 之前必須有超過半數的 follower ACK,即必須有超過半數節點的服務器的事務日誌上有該提案的proposal ,因此,只要有合法數量的節點正常工作,就必須有一個節點保存了所有被commit 消息的proposal狀態。

2、另外一個,zxid 是64 位,高32位是epoch編號,每經過一次Leader 選舉產生一個新的leader,新的leader 會將epoch號 + 1,低32位是消息計數器,每接受到一條消息這個值 + 1,新leader 掛了以後重啓,肯定小於當前新leader。當老的 leader 作爲follower 接入新的leader 後,新的leader 會將所有的擁有舊的epoch 號的未被Commit 的proposal清除。

三、關於ZXID

前面一直提到的zxid,也就是事務id,那麼這個id具體起到什麼作用?以及這個id如何生成的?

爲了保證事務的順序一致性,zookeeper 採用了遞增的事務id號(zxid)來標識事務。所有的提議(proposal) 都在被提出的時候加上了zxid。實現中zxid 是一個64位的數字,

高32位是epoch(ZAB協議通過epoch 編號來區分 Leader週期變化的策略)用來標識leader 關係是否改變,每次一個leader被選出來,它都會有一個新的 epoch = (原來的epoch + 1),標識當前屬於新的leader的統治時期。

低32位用於遞增計數

epoch:可以理解爲當前集羣所處的年代或者週期,每個leader 就像皇帝,都有自己的年號,所以每次改朝換代,leader 變更之後,都會在前一個年代的基礎上加1。這樣就算舊的leader 崩潰恢復之後,也沒有人聽他的了,因爲follower 只聽從當前年代餓leader 的命令。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章