Zookeeper的基本概念和重要特性

1. 什麼是Zookeeper

Zookeeper是大數據生態圈中的重要組件,若是你作過相關開發的話,應該常常能看到它的身影。其由雅虎開源併成爲Apache的頂級項目。用一句話對其進行定義就是:它是一套高吞吐的分佈式協調系統。從中咱們能夠知道Zookeeper至少具備如下特色:node

  • 1.Zookeeper的主要做用是爲分佈式系統提供協調服務,包括但不限於:分佈式鎖,統一命名服務,配置管理,負載均衡,主控服務器選舉以及主從切換等。

  • 2.Zookeeper自身一般也以分佈式形式存在。一個Zookeeper服務一般由多臺服務器節點構成,只要其中超過一半的節點存活,Zookeeper便可正常對外提供服務,因此Zookeeper也暗含高可用的特性。客戶端能夠經過TCP協議鏈接至任意一個服務端節點請求Zookeeper集羣提供服務,而集羣內部如何通訊以及如何保持分佈式數據一致性等細節對客戶端透明。以下圖所示

  • 3.Zookeeper是以高吞吐量爲目標進行設計的,故而在讀多寫少的場合有很是好的性能表現。以下圖所示

縱軸爲每秒響應的客戶端請求數,橫軸爲讀請求所佔百分比。從圖中能夠清晰的看到,隨着讀請求所佔百分比的提升,Zookeeper的QPS也不斷提升。
Zookeeper具備高吞吐特性的主要緣由有如下幾點:算法

1.Zookeeper集羣的任意一個服務端節點均可以直接響應客戶端的讀請求(寫請求會不同些,下面會詳談),而且能夠經過增長節點進行橫向擴展。這是其吞吐量高的主要緣由服務器

2.Zookeeper將全量數據存儲於內存中,從內存中讀取數據不須要進行磁盤IO,速度要快得多。併發

3.Zookeeper放鬆了對分佈式數據的強一致性要求,即不保證數據實時一致,容許分佈式數據通過一個時間窗口達到最終一致,這也在必定程度上提升了其吞吐量。負載均衡

而寫請求,或者說事務請求,由於要進行不一樣服務器結點間狀態的同步,必定程度上會影響其吞吐量。故而簡單的增長Zookeeper的服務器節點數量,對其吞吐量的提高並不必定能起到正面效果。服務器節點增長,有利於提高讀請求的吞吐量,但會延長服務器節點數據的同步時間,必須視具體狀況在這二者之間取得一個平衡。分佈式

2. Zookeeper集羣角色

在Zookeeper集羣中,分別有Leader,Follower和Observer三種類型的服務器角色。性能

  • Leader
    Leader服務器在整個正常運行期間有且僅有一臺,集羣會經過選舉的方式選舉出Leader服務器,由它同統一處理集羣的事務性請求以及集羣內各服務器的調度。大數據

  • Follower
    Follower的主要職責有如下幾點:
    • 1.參與Leader選舉投票
    • 2.參與事務請求Proposal的投票
    • 3.處理客戶端非事務請求(讀),並轉發事務請求(寫)給Leader服務器。
  • Observer
    Observer是弱化版的Follower。其像Follower同樣可以處理非事務也就是讀請求,並轉發事務請求給Leader服務器,可是其不參與任何形式的投票,不論是Leader選舉投票仍是事務請求Proposal的投票。引入這個角色主要是爲了在不影響集羣事務處理能力的前提下提高集羣的非事務處理的吞吐量。設計

3. Zookeeper的數據模型

Zookeeper將數據存儲於內存中,具體而言,Znode是存儲數據的最小單元。而Znode被以層次化的結構進行組織,形容一棵樹。其對外提供的視圖相似於Unix文件系統。樹的根Znode節點至關於Unix文件系統的根路徑。正如Unix中目錄下能夠有子目錄同樣,Znode結點下也能夠掛載子結點,最終造成以下所示結構。

以文件系統進行類比的話,Znode自然具備目錄和文件兩重屬性:即Znode既能夠當作文件往裏面寫東西,又能夠當作目錄在下面掛載其餘Znode。固然,因爲Znode具備不一樣的類型,後半部分並不徹底準確。

3.1 Znode的類型

Znode按其生命週期的長短能夠分爲持久結點(PERSISTENT)和臨時結點(EPHEMERAL);在建立時還可選擇是否由Zookeeper服務端在其路徑後添加一串序號用來區分同一個父結點下多個結點建立的前後順序。
通過組合就有如下4種Znode結點類型

  • 1.持久結點(PERSISTENT)
    最多見的Znode類型,一旦建立將在一直存在於服務端,除非客戶端經過刪除操做進行刪除。持久結點下能夠建立子結點。

  • 2.持久順序結點(PERSISTENT_SEQUENTIAL)
    在具備持久結點基本特性的基礎上,會經過在結點路徑後綴一串序號來區分多個子結點建立的前後順序。這工做由Zookeeper服務端自動給咱們作,只要在建立Znode時指定結點類型爲該類型。

  • 3.臨時結點(EPHEMERAL)
    臨時結點的生命週期和客戶端會話保持一致。客戶端段會話存在的話臨時結點也存在,客戶端會話斷開則臨時結點會自動被服務端刪除。臨時結點下不能建立子結點。

  • 4.臨時順序結點(EPHEMERAL_SEQUENTIAL)
    具備臨時結點的基本特性,又有順序性。

3.2 Znode的結構

Znode結構主要由存儲於其中的數據信息和狀態信息兩部分構成,經過get 命令獲取一個Znode結點的信息以下

第一行存儲的是ZNode的數據信息,從cZxid開始就是Znode的狀態信息
Znode的狀態信息比較多,挑幾個比較重要的講

  • czxid:
    即Created ZXID,表示建立該Znode結點的事務ID

  • mzxid:
    即Modified ZXID,表示最後一次更新該結點的事務ID

  • version
    該Znode結點的版本號。每一個Znode結點被建立時版本號都爲0,每更新一次都會致使版本號加1,即便更新先後Znode存儲的值沒有變化版本號也會加1。version值能夠形象的理解爲Znode結點被更新的次數。Znode狀態信息中的版本號信息,使得服務端能夠對多個客戶端對同一個Znode的更新操做作併發控制。整個過程和java中的CAS有點像,是一種樂觀鎖的併發控制策略,而version值起到了衝突檢測的功能。客戶端拿到Znode的version信息,並在更新時附上這個version信息,服務端在更新Znode時必須必須比較客戶端的version和Znode的實際version,只有這兩個version一致時纔會進行修改。

4. Zookeeper的事件監聽機制

Zookeeper中能夠經過Watcher來實現事件監聽機制。客戶端能夠向服務端註冊Watcher用以監聽某些事件,一旦該事件發生,服務端即會向客戶端發送一個通知。其主要工做流程以下圖所示

具體而言,Watcher是Zookeeper原生API中提供的事件監聽接口,用戶要實現事件監聽必須實現該接口並重寫process(WatchedEvent event)方法,該方法定義了客戶端在接收到服務端事件通知後的回調邏輯。究竟服務端的什麼事件能夠被監聽?按通知狀態劃分有SyncConnected,Disconnected,Expired,AuthFailed等好多種,這裏主要講下SyncConnected狀態下的幾種事件類型:

  • Node(-1)
    客戶端與服務端成功創建會話

  • NodeCreated(1)
    Watcher監聽的對應Znode被建立

  • NodeDeleted(2)
    Watcher監聽的Znode被刪除

  • NodeDataChanged(3)
    Watcher監聽的Znode的數據內容被改變,注意即便變動先後的數據內容徹底同樣也會觸發該事件,或者理解成該事件的觸發條件是Znode的版本號變動也沒問題

  • NodeChildrenChanged(4)
    Watcher監聽的對應Znode的子結點發生變動

Zookeeper的事件監聽機制有如下特性:

  • 1.當監聽器監聽的事件被觸發,服務端會發送通知給客戶端,但通知信息中不包括事件的具體內容。以監聽ZNode結點數據變化爲例,當Znode的數據被改變,客戶端會收到事件類型爲NodeDataChanged的通知,但該Znode的數據改變成了什麼客戶端沒法從通知中獲取,須要客戶端在收到通知後手動去獲取。

  • 2.Watcher是一次性的。一旦被觸發將會失效。若是須要反覆進行監聽就須要反覆進行註冊。這麼設計是爲了減輕服務端的壓力,可是對開發者而言倒是至關不友好,不過不用着急,能夠經過一些Zookeeper的開源客戶端輕鬆實現對某一事件的永久監聽。

5. Zookeeper如何保證分佈式數據一致性——ZAB協議

Zookeeper採用ZAB(Zookeeper Atomic Broadcast)協議來保證分佈式數據一致性。ZAB並非一種通用的分佈式一致性算法,而是一種專爲Zookeeper設計的崩潰可恢復的原子消息廣播算法。ZAB協議包括兩種基本模式:崩潰恢復模式和消息廣播模式。崩潰恢復模式主要用來在集羣啓動過程,或者Leader服務器崩潰退出後進行新的Leader服務器的選舉以及數據同步;消息廣播模式主要用來進行事務請求的處理。下面就從這兩個方面來介紹

5.1 事務請求的處理流程

ZAB協議的核心是定義了對事務請求的處理方式,整個過程能夠歸納以下:

  • 1.全部的事務請求都交由集羣的Leader服務器來處理,Leader服務器會將一個事務請求轉換成一個Proposal(提議),併爲其生成一個全局遞增的惟一ID,這個ID就是事務ID,即ZXID,Leader服務器對Proposal是按其ZXID的前後順序來進行排序和處理的。
  • 2.以後Leader服務器會將Proposal放入每一個Follower對應的隊列中(Leader會爲每一個Follower分配一個單獨的隊列),並以FIFO的方式發送給Follower服務器。
  • 3.Follower服務器接收到事務Proposal後,首先以事務日誌的方式寫入本地磁盤,而且在成功後返回Leader服務器一個ACK響應。
  • 4.Leader服務器只要收到過半Follower的ACK響應,就會廣播一個Commit消息給Follower以通知其進行Proposal的提交,同時Leader自身也會完成Proposal的提交。

整個過程以下圖所示

5.2 Leader服務器的選舉流程

當集羣中不存在Leader服務器時集羣會進行Leader服務器的選舉,這一般存在於兩種狀況:1.集羣剛啓動時 2.集羣運行時,但Leader服務器因故退出。集羣中的服務器會向其餘全部的Follower服務器發送消息,這個消息能夠形象化的稱之爲選票,選票主要由兩個信息組成,所推舉的Leader服務器的ID(即配置在myid文件中的數字),以及該服務器的事務ID,事務表示對服務器狀態變動的操做,一個服務器的事務ID越大,則其數據越新。整個過程以下所述:

  • 1.Follower服務器投出選票(SID,ZXID),第一次每一個Follower都會推選本身爲Leader服務器,也就是說每一個Follower第一次投出的選票是本身的服務器ID和事務ID。
  • 2.每一個Follower都會接收到來自於其餘Follower的選票,它會基於以下規則從新生成一張選票:比較收到的選票和本身的ZXID的大小,選取其中最大的;若ZXID同樣則選取SID即服務器ID最大的。最終每一個服務器都會從新生成一張選票,並將該選票投出去。

這樣通過多輪投票後,若是某一臺服務器獲得了超過半數的選票,則其將當前選爲Leader。由以上分析可知,Zookeeper集羣對Leader服務器的選擇具備偏向性,偏向於那些ZXID更大,即數據更新的機器。

整個過程以下圖所示

6. Zookeeper如何進行服務器故障的容錯

Zookeeper經過事務日誌和數據快照來避免由於服務器故障致使的數據丟失。

  • 事務日誌是指服務器在更新內存數據前先將事務操做以日誌的方式寫入磁盤,Leader和Follower服務器都會記錄事務日誌。
  • 數據快照是指週期性經過深度遍歷的方式將內存中的樹形結構數據轉入外存快照中。但要注意這種快照是"模糊"的,由於可能在作快照時內存數據發生了變化。可是由於Zookeeper自己對事務操做進行了冪等性保證,故在將快照加載進內存後會經過執行事務日誌的方式來說數據恢復到最新狀態。

7. 參考資料

  • 《從PAXOS到ZOOKEEPER分佈式一致性原理與實踐》
  • 《大數據日知錄》
相關文章
相關標籤/搜索