注:出於記錄對 zookeeper 的學習研究成果目的,並分享經驗,根據官方文檔翻譯整理而成本文,原文地址: http://zookeeper.apache.org/doc/trunk/zookeeperOver.html html
ZooKeeper:一個用於分佈式應用的分佈式協調服務java
Zookeeper 是一個分佈式的、開源的協調服務,用在分佈式應用程序中。它提出了一組簡單的原語,分佈式應用程序能夠基於這些原語之上構建更高層的分佈式服務用於實現同步、配置管理、分組和命名等。Zookeeper 設計的容易進行編程,它使用一種相似於文件系統的目錄樹結構的數據模型,以 java 方式運行,有 java 和 c 的綁定(binding)。node
協調服務總所周知地難於正確實現,尤爲容易產生諸如爭用條件、死鎖等錯誤。Zookeeper 背後的動機就是減輕分佈式應用程序從頭作起實現協調服務的難度。算法
設計目標數據庫
Zookeeper 是簡單的,它使分佈式進程能夠經過一種相似於標準文件系統的共享的層次化的命名空間進行相互協調。命名空間由稱爲 znode 的數據記錄組成,在 Zookeeper 的語義裏,znode 相似於文件和目錄。不一樣於典型的爲存儲而設計的文件系統,ZooKeeper 的數據是保持在內存中的,這意味着能夠達到高吞吐量和低延遲。apache
Zookeeper 的實現着重於高性能、高可用性和嚴格的順序訪問。在性能方面, Zookeeper 適用於大型的分佈式系統。在可靠性方面,Zookeeper 可以避免單點失效。嚴格順序意味着能夠在客戶端實現複雜的同步原語。
編程
Zookeeper 是複製的(replicated),就像它協調的分佈式進程同樣,Zookeeper 自身也在被稱爲「ensemble」 的一組主機之間進行復制。緩存
組成 Zookeeper 服務(Service)的每一個服務器(server)必須相互知道對方。它們(Server)維護着一份保持在內存中的狀態鏡像,以及持久存儲的事務日誌和快照。只要這些服務器中的大多數是可用的,整個 Zookeeper 服務就是可用的。服務器
客戶端鏈接到單個 Zookeeper Server,維持着一個 TCP 鏈接,經過該鏈接進行發送請求,獲取回覆,獲取監視事件,以及發送心跳。若是該TCP鏈接中斷了,客戶端將鏈接到另一個服務器。併發
Zookeeper 是順序的。Zookeeper 用一個數字標記每一次更新,以反映全部 Zookeeper 事務的順序。併發的操做能夠這些次序來實現更高層的抽象,好比同步原語。
Zookeeper 是快速的。在應對以「讀」爲主的負載時尤爲地快速。Zookeeper 的應用程序運行在數以千計的計算機上,而當「讀」遠多於「寫」,讀寫比達到 10 比 1 左右時,表現最好。
數據模型和層次化的命名空間
ZooKeeper 採用的命名空間很像標準的文件系統。一個名稱由連續的以斜線"/"分隔的路徑元素組成。命名空間中的每個節點都經過一個路徑惟一標識。
Zookeeper 命名空間 |
節點和瞬時節點(Nodes and ephemeral nodes)
與標準的文件系統不一樣的是,Zookeeper 命名空間中的每個節點能夠既有數據同時也有子節點。就像是有那樣一種文件系統,容許一個文件同時也是一個目錄。(Zookeeper 設計用於保存協調數據:狀態信息、配置、地址信息等等,因此這些保存在節點中的數據一般都很小,在 Byte 到 KB 的範圍。)爲了更明晰一些,Zookeeper 使用「znode」這一術語來表示咱們談論的這些數據節點。
Znode 維護了一個屬性結構,其中包含了表示數據改變、訪問控制列表(ACL)改變的版本號、時間戳,可用於緩存校驗、協調更新。每次一個 znode 的數據發生改變,版本號隨之遞增。當一個客戶端檢索數據時,同時也收到數據對應的版本號。
命名空間中的每一個 znode 的數據的讀寫都是原子的。讀取一個znode將得到其所有的數據,而寫入則替換其所有的數據。每一個節點有一個訪問控制列表(Access Control List (ACL) )用於約束什麼樣的訪問者能夠進行哪些操做。
ZooKeeper 還有「瞬時節點」(emphemeral node)的概念。當建立瞬時節點的客戶端會話一直保持活動,瞬時節點就一直存在。而當會話終結時,瞬時節點被刪除。
條件更新和監視(Conditional updates and watches)
ZooKeeper 支持「監視」(watch)的概念。客戶端能夠在 znode 上設置一個監視(watch)。當 znode 發生改變時,「監視」被觸發同時被移除。當「監視」被觸發時,客戶端會收到一個描述了 znode 的變動的數據包。若是客戶端和Zookeeper服務器之間的鏈接斷開時,客戶端將會收到一個本地通知。
保證(Guarantees)
Zookeeper 很快速也很簡單。不過,因爲它的目標是做爲構建諸如「同步」這類更復雜服務的基礎,它提供了一些的一組保證:
簡單的API
Zookeeper 的設計目標之一就是提供簡單的編程接口。因而,它只提供瞭如下的操做:
create : 在(命名空間)樹的一個特定地址上建立一個節點。
delete : 刪除一個節點。
exists : 檢測在一個地址上是否存在節點。
get data : 從節點讀取數據。
set data :將數據寫入節點。
get children :檢索子節點列表。
sync : 等待數據傳播完成。
實現
Zookeeper 組件圖展現了 Zookeeper 服務的高層組件。除了「Request Processor」,構成 Zookeeper 服務的全部服務器都會複製一份這些組件的拷貝。
Zookeeper 組件 |
「Replicated Database」 是一個內存數據庫,包含了整個數據樹。全部更改都會記錄到磁盤以即可恢復。數據寫入在應用到內存數據庫以前,會先序列化到磁盤。
每個 Zookeeper 服務器都向客戶端提供服務,客戶端鏈接到一個確切的Zookeeper服務器提交請求。讀請求從服務器數據庫的本地拷貝中獲取。改變Zookeeper服務狀態的請求、寫入請求經過一個一致性協議進行處理。
做爲協議的一部分,客戶端的全部寫入請求都被轉發到一個單獨的服務器,該服務器被稱爲 leader。而其他的服務器,被稱爲 follower,從leader接收消息提案(proposal)並對消息的交付取得一致。消息層維護 leader 失效時的更新替換以及 leader 和 follower 之間的同步。
Zookeeper 使用自定義的原子消息協議。因爲消息層是原子的,Zookeeper 能夠保證本地的複製品不會不一致。當 leader 收到一個寫入請求時,它計算系統所處的狀態以及什麼時候應用寫入請求,並將此轉換爲一個事務,包含新的狀態。
使用
Zookeeper 的編程接口特地地定義得很簡單。然而,經過這些編程接口能夠更高階的操做,例如同步原語,成員分組,全部權,等等。
性能
Zookeeper 被設計爲高性能。但實際是否如此呢?在雅虎研發中心的 Zookeeper 開發團隊的研究結果代表的確如此。(參見下圖:Zookeeper 吞吐量隨讀寫比的變化)。在「讀」多於「寫」的應用程序中尤爲地高性能,由於「寫」會致使在全部的服務器間同步狀態。(「讀」多於「寫」是協調服務的典型場景。)
Zookeeper 吞吐量隨讀寫比的變化 |
圖「Zookeeper 吞吐量隨讀寫比的變化」 是 Zookeeper3.2 版本運行於 Dual 2Gh Xeon + 2 個 15K RPM 的 SATA 硬盤驅動器的服務器上的結果。一個驅動器用做 Zookeeper 專用的日誌設備。快照寫到操做系統驅動器。寫請求是 1K 數據的寫入而讀請求是 1K 的數據讀取。「Servers」標出了 Zookeeper Ensemble 的大小,即組成 Zookeeper 服務的服務器的數量。大約30臺其它的服務器被用做模擬客戶端。Zookeeper Ensemble 被配置爲不容許客戶端鏈接到 Leader 。
注:3.2版本的讀/寫性能相對於3.1版本之前有最多達2倍的提高。
基準測試也代表了 Zookeeper 的可靠性。圖「錯誤發生的狀況下的可靠性」展現了 Zookeeper 是如何應對各類不一樣的失效的。圖中標註的事件以下:
一、一個 Follower 失效而後恢復。
二、另外一個不一樣的 Follower 失效而後恢復。
三、Leader 失效。
四、兩個 Follower 失效而後恢復。
五、另外一個 Leader 失效。
錯誤發生的狀況下的可靠性(Reliability in the Presence of Errors) |
從這張圖中能夠獲得幾點重要的結果。首先,若是 follower 失效並快速恢復,Zookeeper 可以維持高吞吐量,儘管存在失效。但也許更重要的是,leader 選舉算法使系統足夠快地恢復,避免了吞吐量的整體降低。從觀察結果來看,Zookeeper 花了不到 200 毫秒的時間選舉出了一個新的 leader。第三,只要 follower 恢復,Zookeeper 的吞吐量可以再次上升到剛開始處理請求時的水平。
Zookeeper 已經被成功地用在許多工業級的應用。在雅虎,Zookeeper 被用做雅虎消息中間件的協調和失效恢復服務,該系統是一個高伸縮性的發佈訂閱系統,管理着成千上萬的主題複製和數據分發。Zookeeper 還被用在雅虎爬蟲的抓取服務上,用於管理失效恢復。許多雅虎的廣告系統也用 Zookeeper 實現可靠的服務。
咱們鼓勵全部的用戶和開發者都加入社區,並貢獻他們的專業知識。更多詳細信息請參見 Zookeeper Project on Apache。