咱們都知道 Zookeeper 是基於 ZAB 協議實現的,在介紹 ZAB 協議以前,先回顧一下 Zookeeper 的起源與發展。java
Zookeeper 到底是在什麼樣的時代背景下被提出?爲了解決了哪些棘手的問題?面試
Zookeeper 最先起源於雅虎研究院的一個研究小組。當時,研究人員發現,在雅虎的不少大型系統基本都須要依賴一個相似的系統來進行分佈式協調,可是這些系統都存在分佈式單點問題,因此雅虎的開發人員就試圖開發出一個通用的無單點問題的分佈式協調框架,以便讓開發人員將精力集中在處理業務邏輯上。算法
因而,Zookeeper 就誕生了!數據庫
Zookeeper 的出現不只解決了分佈式系統下數據一致性的問題,並且經歷過線上驗證,不管是從性能、易用性、穩定性上來講,都是工業級產品的標準。能夠說在分佈式系統中具備不可替代的核心地位,Hadoop、HBase、Storm 和 Solr 等大型分佈式系統都已經將 Zookeeper 做爲其核心組件,用於分佈式協調。即使 Zookeeper 如此優秀,可是 Zookeeper 依然是免費且開源的,全世界成千上萬的開發者都關注着它,陪同着一塊兒成長和發展。緩存
做爲一個開發者不管是爲了應付面試、晉升仍是我的技術成長的須要,都須要對 Zookeeper 有所瞭解,而學習 Zookeeper 的關鍵就是理解其核心部分: 服務器
ZAB 協議, 全稱(Zookeeper Atomic Broadcast)Zookeeper 原子消息廣播協議。微信
它與 Paxos 相似,也是一種數據一致性的算法。網絡
在 ZAB 協議的開發設計人員在協議設計之初並無要求 ZAB 具備很好的擴展性,最初只是爲了雅虎公司內部哪些高吞吐量、低延遲、健壯、簡單的分佈式系統場景設計的。基於 ZAB 協議,Zookeeper 實現了一種主備模式的系統架構來保持集羣中各副本之間數據的一致性,簡單架構圖以下:架構
Zookeeper 用一個單一的主進程來接收並處理客戶端的全部事物請求,並採用 ZAB 的原子廣播協議將服務器數據狀態以事物 Proposal 的形式廣播到全部的副本進程中去。這樣的模式就保證了,在同一時刻只有一個主進程來廣播服務器的狀態更變,所以可以很好地處理客戶端大量的併發請求,這在 ZAB 協議中叫:消息廣播。併發
除此以外,在分佈式環境中事物的執行順序也會存在必定的前後關係,好比:事務 C 的寫入須要依賴事務 B 的寫入,而事務 B 寫入須要依賴事務 A 寫入。這種先後依賴的順序也對 ZAB 協議提出了一個要求:ZAB 協議須要保證若是一個狀態的變動被處理了,那麼全部其依賴的狀態變動都已經被提早處理了。也就是須要順序執行。
另外除了能正常廣播消息、消息的順序執行,主進程也可能隨時會由於斷電、機器宕機等異常狀況沒法提供服務,所以,ZAB 協議還須要作到在當前主進程出現上述異常狀況的時候依然可以正常工做,這在 ZAB 協議中叫:崩潰恢復。
因此整個 ZAB 協議須要具有的核心特性已經被描述出來了,處理事務的請求的方式能夠簡單理解爲:
全部的事務請求必須由一個全局惟一的服務器來協調處理,這樣的服務器叫:Leader 服務器。其餘的服務器被稱爲 Follower 服務器。Leader 服務器將客戶端事務請求轉化成一個事務 Prososal(提議),並將改 Proposal 分發給集羣中全部的 Follower 服務器。以後 Leader 服務器接收了正確的反饋後,那麼 Leader 就會再次向全部的 Follower 服務器分發 Commit 消息,要求將前一個 Proposal 提交。
這就簡單闡述了ZAB 協議中消息廣播模式的部份內容。
ZAB 協議的包括兩種模式:崩潰恢復、消息廣播。
既然有兩種模式,那 Zookeeper 集羣何時進入奔潰恢復模式?何時進入消息廣播模式呢?
在進入奔潰恢復模式時 Zookeeper 集羣會進行 Leader 選舉,通常有兩種狀況會發生選舉:
選舉出 Leader 服務器後,會進入消息廣播模式,開始接收處理客戶端的請求,前文已經描述,這裏再也不贅述。
在深刻講解 ZAB 協議的兩個模式以前,先解釋 Zookeeper 的幾個相關概念,方便理解 ZAB 協議:
在前面提到 Zookeeper 的集羣中的服務器有 Leader 和 Follower ,但實際在 ZAB 協議中 Zookeeper 有三種角色,分別是 Leader、Folower、Observer,它們的分工各有不一樣:
Leader :負責整個Zookeeper 集羣工做機制中的核心,主要工做有一下兩個:
Follower :它是 Leader 的追隨者,其主要工做有三個:
在知道了 Zookeeper 中有三種角色後,不經提問: Zookeeper 是如何知道本身目前是什麼角色的呢?
在 ZAB 協議中定義:經過自身的狀態來區分本身的角色的,在運行期間各個進程可能出現如下三種狀態之一:
在組成 ZAB 協議的全部進程啓動的時候,初始化狀態都是 LOOKING 狀態,此時進程組中不存在 Leader,選舉以後纔有,在進行選舉成功後,就進入消息廣播模式,此時 Zookeeper 集羣中的角色狀態就再也不是 LOOKING 狀態。
前文咱們知道 zookeeper 消息有嚴格的因果關係,所以必須將每個事務請求按照前後順序來進行排序與處理。那 Zookeeper 是如何保持請求處理的順序的呢?其中很是關鍵的點就是 ZXID。
那 ZXID 到底是怎麼發揮做用的呢?
Leader 服務器在接收到事務請求後,會爲每一個事務請求生成對應的 Proposal 來進行廣播,而且在廣播事務 Proposal 以前,Leader 服務器會首先爲這個事務 Proposal 分配一個全局單調遞增的惟一 ID ,咱們稱之爲事務 ID(即 ZXID)。
ZXID 的設計也頗有特色,是一個全局有序的 64 位的數字,能夠分爲兩個部分:
這裏低 32 位 counter(計數器)單調遞增還好理解,高 32 位 epoch(紀元)每次選舉加 1 也許有些同窗就有疑問了,爲何 epoch(紀元)每次選須要舉加 1 ,它在整個 ZAB 協議中有什麼做用?
咱們知道每當選舉產生一個新的 Leader 服務器時生成一個新的 epoch(紀元)值,而在前文咱們知道,服務運行過程當中觸發選舉 Leader 的條件是:Leader 服務器的出現網絡中斷、奔潰退出、重啓等異常狀況,或者當集羣中半數的服務器與該 Leader 服務器沒法通訊時。
這說明整個 Zookeeper 集羣此時處於一個異常的狀況下,而在發生異常前,消息廣播進行到哪一步驟咱們根本不知道,集羣中的其餘 Follower 節點從這種崩潰恢復狀態從新選舉出 Leader 後,若是老 Leader 又恢復了鏈接進入集羣。此時老 Leader 的 epoch 確定會小於新 Leader 的 epoch,這時就將老 Leader 變成 Follower,對新的 Leader 進行數據同步。即使這時老 Leader 對其餘的 Follower 節點發送了請求,Follower 節點也會比較 ZXID 的值,由於高 32 位加 1 了, Follower 的 epoch(紀元)大於老 Leader 的 epoch(紀元),因此 Follower 會忽略這個請求。
這像改朝換代同樣,前朝的劍不能斬本朝的官。
知道了這些名詞,和上文提到的零散的知識點,其實崩潰恢復模式和消息廣播模式的過程你們大體有所瞭解了。
先看看消息廣播模式吧!
消息廣播的模式的過程簡圖以下所示:
整個過程相似一個二階段提交的過程,但卻有所不一樣,ZAB 協議簡化了二階段提交模型,在超過半數的 Follower 服務器已經反饋 ACK 以後就開始提交事務 Prososal 了,無需等待全部服務器響應。
結合上圖,看看消息廣播的具體細節:
在畫一張詳細點的流程圖,更直觀:
這就完成了整個消息廣播了!
前文已經反覆提過崩潰恢復模式了,其實就是從新選舉出新的 Leader 服務器,選舉完成後 Follower 服務器在再去同步 Leader 的數據。
運行中的服務再次進行從新選舉,必定是出現某種異常,咱們知道在出現異常狀況以前 Leader 的消息廣播可能會處在任何一個階段,有可能客戶端的請求只是在 Leader 服務器上提出並未被提交,也可能請求已經被 Leader 服務器提交。
ZAB 協議對於不一樣階段的出現的數據不一致的狀況作了兼容,保證:
針對以上的兩個要求,在進行 Leader 選舉時,之須要選舉出集羣中 ZXID 最大的事務 Proposal 便可,這樣就能夠省去 Leader 服務器檢查 Proposal 的提交和丟棄工做了。由於 Leader 服務器的事務是最大的,一切以 Leader 服務器的數據爲標準便可。
ZXID 在集羣中其實並非惟一的,因此也有可能出現多 Follower 服務器 ZXID 相同的狀況,這時候就須要比較 Zookeeper 的 SID 值。什麼是 SID?SID 是一個數字,和 zookeeper 的 myid 一致,myid 就不要解釋了,安裝過 Zookeeper 的都知道,每臺服務器都須要配置一個這樣的文件,裏面只有一個數字,用來標識這臺服務器。由於每臺機器的 myid 配置都不同,因此集羣選舉的時不會出現相等的狀況。
選舉時,比較大小的源碼以下:
前面已經說過,出現選舉 Leader 可能會出現兩種狀況:
但不管是啓動期仍是運行期進行 Leader 選舉,其選舉過程都差不太多,我簡單畫個流程圖:
結合上圖,奔潰恢復模式下 Leader 選舉的過程細節以下:
發起投票時有兩種狀況:
這就是崩潰恢復模式下選舉 Leader 的過程了!
下面再簡單介紹下數據同步的四種策略,這四種同步策略保證了Zookeeper 集羣中的數據一致性,也解決了前文提出的兩個問題,兼容了各類數據不一致的場景。
在數據同步以前,Leader 服務器會進行數據同步的初始化,首先會從 Zookeeper 的內存數據庫中提取出事務前期對應的提議緩存隊列,同時會初始化三個 ZXID 的值:
根據這三個參數,就能夠肯定四種同步方式,分別爲:
直接差別化同步
先回滾在差別化同步
僅回滾同步
全量同步
這就是四種同步策略,這幾種同步方式也解決了上文提出的問題:
這些就是整個 ZAB 協議中崩潰恢復的內容。
ZAB協議看起來和Paxos有着相同之處,但它並非Paxos的典型實現,其實仍是有一些區別,ZAB協議中額外添加了一個同步的階段,二者設計目標也不太同樣,ZAB協議主要用於構建一個高可用的分佈式數據主備系統,而Paxos算法則是用於構建一個分佈式一致性的狀態機。
Zookeeper 做爲出色的分佈式協調服務,目前讀 QPS 達到 12w,出色的性能也讓開發者更加青睞,其 ZAB 協議的核心分爲兩個部分:崩潰恢復、消息廣播。
典型的應用場景有:
除此以外在大數據領域也有應用,例如:
在阿里巴巴集團內部實踐的 Zookeeper 的產品也有不少,如:
咱們都知道 Zookeeper 是基於 ZAB 協議實現的,在介紹 ZAB 協議以前,先回顧一下 Zookeeper 的起源與發展。
Zookeeper 到底是在什麼樣的時代背景下被提出?爲了解決了哪些棘手的問題?
Zookeeper 最先起源於雅虎研究院的一個研究小組。當時,研究人員發現,在雅虎的不少大型系統基本都須要依賴一個相似的系統來進行分佈式協調,可是這些系統都存在分佈式單點問題,因此雅虎的開發人員就試圖開發出一個通用的無單點問題的分佈式協調框架,以便讓開發人員將精力集中在處理業務邏輯上。
因而,Zookeeper 就誕生了!
Zookeeper 的出現不只解決了分佈式系統下數據一致性的問題,並且經歷過線上驗證,不管是從性能、易用性、穩定性上來講,都是工業級產品的標準。能夠說在分佈式系統中具備不可替代的核心地位,Hadoop、HBase、Storm 和 Solr 等大型分佈式系統都已經將 Zookeeper 做爲其核心組件,用於分佈式協調。即使 Zookeeper 如此優秀,可是 Zookeeper 依然是免費且開源的,全世界成千上萬的開發者都關注着它,陪同着一塊兒成長和發展。
做爲一個開發者不管是爲了應付面試、晉升仍是我的技術成長的須要,都須要對 Zookeeper 有所瞭解,而學習 Zookeeper 的關鍵就是理解其核心部分:
ZAB 協議, 全稱(Zookeeper Atomic Broadcast)Zookeeper 原子消息廣播協議。
它與 Paxos 相似,也是一種數據一致性的算法。
在 ZAB 協議的開發設計人員在協議設計之初並無要求 ZAB 具備很好的擴展性,最初只是爲了雅虎公司內部哪些高吞吐量、低延遲、健壯、簡單的分佈式系統場景設計的。基於 ZAB 協議,Zookeeper 實現了一種主備模式的系統架構來保持集羣中各副本之間數據的一致性,簡單架構圖以下:
Zookeeper 用一個單一的主進程來接收並處理客戶端的全部事物請求,並採用 ZAB 的原子廣播協議將服務器數據狀態以事物 Proposal 的形式廣播到全部的副本進程中去。這樣的模式就保證了,在同一時刻只有一個主進程來廣播服務器的狀態更變,所以可以很好地處理客戶端大量的併發請求,這在 ZAB 協議中叫:消息廣播。
除此以外,在分佈式環境中事物的執行順序也會存在必定的前後關係,好比:事務 C 的寫入須要依賴事務 B 的寫入,而事務 B 寫入須要依賴事務 A 寫入。這種先後依賴的順序也對 ZAB 協議提出了一個要求:ZAB 協議須要保證若是一個狀態的變動被處理了,那麼全部其依賴的狀態變動都已經被提早處理了。也就是須要順序執行。
另外除了能正常廣播消息、消息的順序執行,主進程也可能隨時會由於斷電、機器宕機等異常狀況沒法提供服務,所以,ZAB 協議還須要作到在當前主進程出現上述異常狀況的時候依然可以正常工做,這在 ZAB 協議中叫:崩潰恢復。
因此整個 ZAB 協議須要具有的核心特性已經被描述出來了,處理事務的請求的方式能夠簡單理解爲:
全部的事務請求必須由一個全局惟一的服務器來協調處理,這樣的服務器叫:Leader 服務器。其餘的服務器被稱爲 Follower 服務器。Leader 服務器將客戶端事務請求轉化成一個事務 Prososal(提議),並將改 Proposal 分發給集羣中全部的 Follower 服務器。以後 Leader 服務器接收了正確的反饋後,那麼 Leader 就會再次向全部的 Follower 服務器分發 Commit 消息,要求將前一個 Proposal 提交。
這就簡單闡述了 ZAB 協議中消息廣播模式的部份內容。
ZAB 協議的包括兩種模式:崩潰恢復、消息廣播。
既然有兩種模式,那 Zookeeper 集羣何時進入奔潰恢復模式?何時進入消息廣播模式呢?
在進入奔潰恢復模式時 Zookeeper 集羣會進行 Leader 選舉,通常有兩種狀況會發生選舉:
選舉出 Leader 服務器後,會進入消息廣播模式,開始接收處理客戶端的請求,前文已經描述,這裏再也不贅述。
在深刻講解 ZAB 協議的兩個模式以前,先解釋 Zookeeper 的幾個相關概念,方便理解 ZAB 協議:
在前面提到 Zookeeper 的集羣中的服務器有 Leader 和 Follower ,但實際在 ZAB 協議中 Zookeeper 有三種角色,分別是 Leader、Folower、Observer,它們的分工各有不一樣:
Leader :負責整個Zookeeper 集羣工做機制中的核心,主要工做有一下兩個:
Follower :它是 Leader 的追隨者,其主要工做有三個:
在知道了 Zookeeper 中有三種角色後,不經提問: Zookeeper 是如何知道本身目前是什麼角色的呢?
在 ZAB 協議中定義:經過自身的狀態來區分本身的角色的,在運行期間各個進程可能出現如下三種狀態之一:
在組成 ZAB 協議的全部進程啓動的時候,初始化狀態都是 LOOKING 狀態,此時進程組中不存在 Leader,選舉以後纔有,在進行選舉成功後,就進入消息廣播模式,此時 Zookeeper 集羣中的角色狀態就再也不是 LOOKING 狀態。
前文咱們知道 zookeeper 消息有嚴格的因果關係,所以必須將每個事務請求按照前後順序來進行排序與處理。那 Zookeeper 是如何保持請求處理的順序的呢?其中很是關鍵的點就是 ZXID。
那 ZXID 到底是怎麼發揮做用的呢?
Leader 服務器在接收到事務請求後,會爲每一個事務請求生成對應的 Proposal 來進行廣播,而且在廣播事務 Proposal 以前,Leader 服務器會首先爲這個事務 Proposal 分配一個全局單調遞增的惟一 ID ,咱們稱之爲事務 ID(即 ZXID)。
ZXID 的設計也頗有特色,是一個全局有序的 64 位的數字,能夠分爲兩個部分:
這裏低 32 位 counter(計數器)單調遞增還好理解,高 32 位 epoch(紀元)每次選舉加 1 也許有些同窗就有疑問了,爲何 epoch(紀元)每次選須要舉加 1 ,它在整個 ZAB 協議中有什麼做用?
咱們知道每當選舉產生一個新的 Leader 服務器時生成一個新的 epoch(紀元)值,而在前文咱們知道,服務運行過程當中觸發選舉 Leader 的條件是:Leader 服務器的出現網絡中斷、奔潰退出、重啓等異常狀況,或者當集羣中半數的服務器與該 Leader 服務器沒法通訊時。
這說明整個 Zookeeper 集羣此時處於一個異常的狀況下,而在發生異常前,消息廣播進行到哪一步驟咱們根本不知道,集羣中的其餘 Follower 節點從這種崩潰恢復狀態從新選舉出 Leader 後,若是老 Leader 又恢復了鏈接進入集羣。此時老 Leader 的 epoch 確定會小於新 Leader 的 epoch,這時就將老 Leader 變成 Follower,對新的 Leader 進行數據同步。即使這時老 Leader 對其餘的 Follower 節點發送了請求,Follower 節點也會比較 ZXID 的值,由於高 32 位加 1 了, Follower 的 epoch(紀元)大於老 Leader 的 epoch(紀元),因此 Follower 會忽略這個請求。
這像改朝換代同樣,前朝的劍不能斬本朝的官。
知道了這些名詞,和上文提到的零散的知識點,其實崩潰恢復模式和消息廣播模式的過程你們大體有所瞭解了。
先看看消息廣播模式吧!
消息廣播的模式的過程簡圖以下所示:
<img src="https://upload-images.jianshu.io/upload_images/2710833-927c4264c545c4e7.png" alt="image.png" />
整個過程相似一個二階段提交的過程,但卻有所不一樣,ZAB 協議簡化了二階段提交模型,在超過半數的 Follower 服務器已經反饋 ACK 以後就開始提交事務 Prososal 了,無需等待全部服務器響應。
結合上圖,看看消息廣播的具體細節:
在畫一張詳細點的流程圖,更直觀:
<img src="https://upload-images.jianshu.io/upload_images/2710833-e53b8b881792203a.png" alt="image.png" />
這就完成了整個消息廣播了!
前文已經反覆提過崩潰恢復模式了,其實就是從新選舉出新的 Leader 服務器,選舉完成後 Follower 服務器在再去同步 Leader 的數據。
運行中的服務再次進行從新選舉,必定是出現某種異常,咱們知道在出現異常狀況以前 Leader 的消息廣播可能會處在任何一個階段,有可能客戶端的請求只是在 Leader 服務器上提出並未被提交,也可能請求已經被 Leader 服務器提交。
ZAB 協議對於不一樣階段的出現的數據不一致的狀況作了兼容,保證:
針對以上的兩個要求,在進行 Leader 選舉時,之須要選舉出集羣中 ZXID 最大的事務 Proposal 便可,這樣就能夠省去 Leader 服務器檢查 Proposal 的提交和丟棄工做了。由於 Leader 服務器的事務是最大的,一切以 Leader 服務器的數據爲標準便可。
ZXID 在集羣中其實並非惟一的,因此也有可能出現多 Follower 服務器 ZXID 相同的狀況,這時候就須要比較 Zookeeper 的 SID 值。什麼是 SID?SID 是一個數字,和 zookeeper 的 myid 一致,myid 就不要解釋了,安裝過 Zookeeper 的都知道,每臺服務器都須要配置一個這樣的文件,裏面只有一個數字,用來標識這臺服務器。由於每臺機器的 myid 配置都不同,因此集羣選舉的時不會出現相等的狀況。
選舉時,比較大小的源碼以下:
<img src="https://upload-images.jianshu.io/upload_images/2710833-bbcba5240c2a1db0.png" alt="image.png" />
前面已經說過,出現選舉 Leader 可能會出現兩種狀況:
但不管是啓動期仍是運行期進行 Leader 選舉,其選舉過程都差不太多,我簡單畫個流程圖:
<img src="https://upload-images.jianshu.io/upload_images/2710833-d87f4a39511a8630.png" alt="image.png" />
結合上圖,奔潰恢復模式下 Leader 選舉的過程細節以下:
發起投票時有兩種狀況:
這就是崩潰恢復模式下選舉 Leader 的過程了!
下面再簡單介紹下數據同步的四種策略,這四種同步策略保證了Zookeeper 集羣中的數據一致性,也解決了前文提出的兩個問題,兼容了各類數據不一致的場景。
在數據同步以前,Leader 服務器會進行數據同步的初始化,首先會從 Zookeeper 的內存數據庫中提取出事務前期對應的提議緩存隊列,同時會初始化三個 ZXID 的值:
根據這三個參數,就能夠肯定四種同步方式,分別爲:
直接差別化同步
先回滾在差別化同步
僅回滾同步
全量同步
這就是四種同步策略,這幾種同步方式也解決了上文提出的問題:
這些就是整個 ZAB 協議中崩潰恢復的內容。
ZAB協議看起來和Paxos有着相同之處,但它並非Paxos的典型實現,其實仍是有一些區別,ZAB協議中額外添加了一個同步的階段,二者設計目標也不太同樣,ZAB協議主要用於構建一個高可用的分佈式數據主備系統,而Paxos算法則是用於構建一個分佈式一致性的狀態機。
Zookeeper 做爲出色的分佈式協調服務,目前讀 QPS 達到 12w,出色的性能也讓開發者更加青睞,其 ZAB 協議的核心分爲兩個部分:崩潰恢復、消息廣播。
典型的應用場景有:
除此以外在大數據領域也有應用,例如:
在阿里巴巴集團內部實踐的 Zookeeper 的產品也有不少,如:
歡迎關注個人我的微信公衆號:java之旅