注:出於記錄對 zookeeper 的學習研究成果目的,並分享經驗,根據官方文檔翻譯整理而成本文,原文地址: http://zookeeper.apache.org/doc/trunk/zookeeperOver.html
ZooKeeper:一個用於分布式應用的分布式協調服務
Zookeeper 是一個分布式的、開源的協調服務,用在分布式應用程序中。它提出了一組簡單的原語,分布式應用程序可以基於這些原語之上構建更高層的分布式服務用於實現同步、配置管理、分組和命名等。Zookeeper 設計的容易進行編程,它使用一種類似於文件系統的目錄樹結構的數據模型,以 java 方式運行,有 java 和 c 的綁定(binding)。
協調服務總所周知地難於正確實現,尤其容易產生諸如爭用條件、死鎖等錯誤。Zookeeper 背后的動機就是減輕分布式應用程序從頭做起實現協調服務的難度。
設計目標
Zookeeper 是簡單的,它使分布式進程可以通過一種類似於標准文件系統的共享的層次化的命名空間進行相互協調。命名空間由稱為 znode 的數據記錄組成,在 Zookeeper 的語義里,znode 類似於文件和目錄。不同於典型的為存儲而設計的文件系統,ZooKeeper 的數據是保持在內存中的,這意味着可以達到高吞吐量和低延遲。
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 很快速也很簡單。不過,由於它的目標是作為構建諸如“同步”這類更復雜服務的基礎,它提供了一些的一組保證:
- 順序一致性 - 來自客戶端的更改請求將會按照它們的發送的順序被應用。
- 原子性 - 更改要么成功,要么失敗,不會存在部分成功或失敗的結果。
- 單一系統映像 - 客戶端會看到 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 是如何應對各種不同的失效的。圖中標注的事件如下:
1、一個 Follower 失效然后恢復。
2、另一個不同的 Follower 失效然后恢復。
3、Leader 失效。
4、兩個 Follower 失效然后恢復。
5、另一個 Leader 失效。
錯誤發生的情況下的可靠性(Reliability in the Presence of Errors) |
![]() |
從這張圖中可以得到幾點重要的結果。首先,如果 follower 失效並快速恢復,Zookeeper 能夠維持高吞吐量,盡管存在失效。但也許更重要的是,leader 選舉算法使系統足夠快地恢復,避免了吞吐量的總體下降。從觀察結果來看,Zookeeper 花了不到 200 毫秒的時間選舉出了一個新的 leader。第三,只要 follower 恢復,Zookeeper 的吞吐量能夠再次上升到剛開始處理請求時的水平。
關於ZooKeeper項目
Zookeeper 已經被成功地用在許多工業級的應用。在雅虎,Zookeeper 被用作雅虎消息中間件的協調和失效恢復服務,該系統是一個高伸縮性的發布訂閱系統,管理着成千上萬的主題復制和數據分發。Zookeeper 還被用在雅虎爬蟲的抓取服務上,用於管理失效恢復。許多雅虎的廣告系統也用 Zookeeper 實現可靠的服務。
我們鼓勵所有的用戶和開發者都加入社區,並貢獻他們的專業知識。更多詳細信息請參見 Zookeeper Project on Apache。