Zookeeper 是一個開源的分佈式協調服務,目前由 Apache 進行維護。Zookeeper 能夠用於實現分佈式系統中常見的發佈/訂閱、負載均衡、命令服務、分佈式協調/通知、集羣管理、Master 選舉、分佈式鎖和分佈式隊列等功能。它具備如下特性:node
Zookeeper 致力於爲那些高吞吐的大型分佈式系統提供一個高性能、高可用、且具備嚴格順序訪問控制能力的分佈式協調服務。它具備如下四個目標:git
Zookeeper 經過樹形結構來存儲數據,它由一系列被稱爲 ZNode 的數據節點組成,相似於常見的文件系統。不過和常見的文件系統不一樣,Zookeeper 將數據全量存儲在內存中,以此來實現高吞吐,減小訪問延遲。github
能夠由一組 Zookeeper 服務構成 Zookeeper 集羣,集羣中每臺機器都會單獨在內存中維護自身的狀態,而且每臺機器之間都保持着通信,只要集羣中有半數機器可以正常工做,那麼整個集羣就能夠正常提供服務。服務器
對於來自客戶端的每一個更新請求,Zookeeper 都會分配一個全局惟一的遞增 ID,這個 ID 反映了全部事務請求的前後順序。網絡
ZooKeeper 將數據存全量儲在內存中以保持高性能,並經過服務集羣來實現高可用,因爲 Zookeeper 的全部更新和刪除都是基於事務的,因此其在讀多寫少的應用場景中有着很高的性能表現。session
Zookeeper 集羣中的機器分爲如下三種角色:數據結構
Zookeeper 客戶端經過 TCP 長鏈接鏈接到服務集羣,會話 (Session) 從第一次鏈接開始就已經創建,以後經過心跳檢測機制來保持有效的會話狀態。經過這個鏈接,客戶端能夠發送請求並接收響應,同時也能夠接收到 Watch 事件的通知。架構
關於會話中另一個核心的概念是 sessionTimeOut(會話超時時間),當因爲網絡故障或者客戶端主動斷開等緣由,致使鏈接斷開,此時只要在會話超時時間以內從新創建鏈接,則以前建立的會話依然有效。負載均衡
Zookeeper 數據模型是由一系列基本數據單元 Znode
(數據節點) 組成的節點樹,其中根節點爲 /
。每一個節點上都會保存本身的數據和節點信息。Zookeeper 中節點能夠分爲兩大類:框架
臨時節點和持久節點均可以添加一個特殊的屬性:SEQUENTIAL
,表明該節點是否具備遞增屬性。若是指定該屬性,那麼在這個節點建立時,Zookeeper 會自動在其節點名稱後面追加一個由父節點維護的遞增數字。
每一個 ZNode 節點在存儲數據的同時,都會維護一個叫作 Stat
的數據結構,裏面存儲了關於該節點的所有狀態信息。以下:
狀態屬性 | 說明 |
---|---|
czxid | 數據節點建立時的事務 ID |
ctime | 數據節點建立時的時間 |
mzxid | 數據節點最後一次更新時的事務 ID |
mtime | 數據節點最後一次更新時的時間 |
pzxid | 數據節點的子節點最後一次被修改時的事務 ID |
cversion | 子節點的更改次數 |
version | 節點數據的更改次數 |
aversion | 節點的 ACL 的更改次數 |
ephemeralOwner | 若是節點是臨時節點,則表示建立該節點的會話的 SessionID;若是節點是持久節點,則該屬性值爲 0 |
dataLength | 數據內容的長度 |
numChildren | 數據節點當前的子節點個數 |
Zookeeper 中一個經常使用的功能是 Watcher(事件監聽器),它容許用戶在指定節點上針對感興趣的事件註冊監聽,當事件發生時,監聽器會被觸發,並將事件信息推送到客戶端。該機制是 Zookeeper 實現分佈式協調服務的重要特性。
Zookeeper 採用 ACL(Access Control Lists) 策略來進行權限控制,相似於 UNIX 文件系統的權限控制。它定義了以下五種權限:
ZAB 協議是 Zookeeper 專門設計的一種支持崩潰恢復的原子廣播協議。經過該協議,Zookeepe 基於主從模式的系統架構來保持集羣中各個副本之間數據的一致性。具體以下:
Zookeeper 使用一個單一的主進程來接收並處理客戶端的全部事務請求,並採用原子廣播協議將數據狀態的變動以事務 Proposal 的形式廣播到全部的副本進程上去。以下圖:
具體流程以下:
全部的事務請求必須由惟一的 Leader 服務來處理,Leader 服務將事務請求轉換爲事務 Proposal,並將該 Proposal 分發給集羣中全部的 Follower 服務。若是有半數的 Follower 服務進行了正確的反饋,那麼 Leader 就會再次向全部的 Follower 發出 Commit 消息,要求將前一個 Proposal 進行提交。
ZAB 協議包括兩種基本的模式,分別是崩潰恢復和消息廣播:
當整個服務框架在啓動過程當中,或者當 Leader 服務器出現異常時,ZAB 協議就會進入恢復模式,經過過半選舉機制產生新的 Leader,以後其餘機器將重新的 Leader 上同步狀態,當有過半機器完成狀態同步後,就退出恢復模式,進入消息廣播模式。
ZAB 協議的消息廣播過程使用的是原子廣播協議。在整個消息的廣播過程當中,Leader 服務器會每一個事物請求生成對應的 Proposal,併爲其分配一個全局惟一的遞增的事務 ID(ZXID),以後再對其進行廣播。具體過程以下:
Leader 服務會爲每個 Follower 服務器分配一個單獨的隊列,而後將事務 Proposal 依次放入隊列中,並根據 FIFO(先進先出) 的策略進行消息發送。Follower 服務在接收到 Proposal 後,會將其以事務日誌的形式寫入本地磁盤中,並在寫入成功後反饋給 Leader 一個 Ack 響應。當 Leader 接收到超過半數 Follower 的 Ack 響應後,就會廣播一個 Commit 消息給全部的 Follower 以通知其進行事務提交,以後 Leader 自身也會完成對事務的提交。而每個 Follower 則在接收到 Commit 消息後,完成事務的提交。
數據的發佈/訂閱系統,一般也用做配置中心。在分佈式系統中,你可能有成千上萬個服務節點,若是想要對全部服務的某項配置進行更改,因爲數據節點過多,你不可逐臺進行修改,而應該在設計時採用統一的配置中心。以後發佈者只須要將新的配置發送到配置中心,全部服務節點便可自動下載並進行更新,從而實現配置的集中管理和動態更新。
Zookeeper 經過 Watcher 機制能夠實現數據的發佈和訂閱。分佈式系統的全部的服務節點能夠對某個 ZNode 註冊監聽,以後只須要將新的配置寫入該 ZNode,全部服務節點都會收到該事件。
在分佈式系統中,一般須要一個全局惟一的名字,如生成全局惟一的訂單號等,Zookeeper 能夠經過順序節點的特性來生成全局惟一 ID,從而能夠對分佈式系統提供命名服務。
分佈式系統一個重要的模式就是主從模式 (Master/Salves),Zookeeper 能夠用於該模式下的 Matser 選舉。可讓全部服務節點去競爭性地建立同一個 ZNode,因爲 Zookeeper 不能有路徑相同的 ZNode,必然只有一個服務節點可以建立成功,這樣該服務節點就能夠成爲 Master 節點。
能夠經過 Zookeeper 的臨時節點和 Watcher 機制來實現分佈式鎖,這裏以排它鎖爲例進行說明:
分佈式系統的全部服務節點能夠競爭性地去建立同一個臨時 ZNode,因爲 Zookeeper 不能有路徑相同的 ZNode,必然只有一個服務節點可以建立成功,此時能夠認爲該節點得到了鎖。其餘沒有得到鎖的服務節點經過在該 ZNode 上註冊監聽,從而當鎖釋放時再去競爭得到鎖。鎖的釋放狀況有如下兩種:
當鎖被釋放後,其餘服務節點則再次去競爭性地進行建立,但每次都只有一個服務節點可以獲取到鎖,這就是排他鎖。
Zookeeper 還能解決大多數分佈式系統中的問題:
更多大數據系列文章能夠參見 GitHub 開源項目: 大數據入門指南