譯自http://zookeeper.apache.org/doc/trunk/zookeeperOver.htmlhtml
ZooKeeper是一個用於分佈式應用的開源分佈式協調服務。它提供了簡單的原語集合,分佈式應用可在這些原語之上構建用於同步、配 置維護、分組和命名的高層服務。ZooKeeper的設計使得編程容易,而且使用相似於普遍熟知的文件系統目錄樹結構的數據模型。它運行在Java環境 中,可是有Java和C語言綁定。node
分佈式協調服務是出了名的可貴編寫正確,很容易出現競爭條件和死鎖之類的錯誤。ZooKeeper的動機是減輕爲分佈式應用開發協調服務的負擔。算法
ZooKeeper讓分佈式進程可經過共享的、與標準文件系統相似的分層名字空間相互協調。名字空間由數據寄存器(在ZooKeeper世界中稱做znode)構成,這與文件和目錄相似。與用於存儲設備的典型文件系統不一樣的是,ZooKeeper在內存中保存數據,這讓其能夠達到高吞吐量和低延遲。數據庫
ZooKeeper的實現很重視高性能、高可用性,以及嚴格的順序訪問。高性能意味着可將ZooKeeper用於大的分佈式系統。可靠性使之可避免單點失敗。嚴格的順序訪問使得客戶端能夠實現複雜的同步原語。apache
與它所協調的進程同樣,ZooKeeper自己也會試圖在一組主機間進行復制,這就是集羣。編程
組成ZooKeeper服務的各個服務器必須相互知道對方。它們在內存中維護狀態和事務日誌,還在永久存儲中維護快照。只要大部分服務器可用,ZooKeeper服務就是可用的。緩存
客戶端鏈接到單個ZooKeeper服務器。客戶端維持一個TCP鏈接,經過這個鏈接發送請求、接收響應、獲取觀察事件,以及發送心跳。若是到服務器的TCP鏈接斷開,客戶端會鏈接到另外一個服務器。服務器
ZooKeeper爲每次更新設置一個反映全部ZooKeeper事務順序的序號。併發操做可以使用序號來實現更高層抽象,如同步原語。併發
在讀操做爲主的負載下特別快。ZooKeeper應用運行在成千上萬臺機器中,在讀操做比寫操做頻繁,兩者比例約爲10:1的狀況下,性能最好。分佈式
ZooKeeper提供的名字空間與標準文件系統很是類似。名字是一個由斜槓/分隔的路徑元素序列。ZooKeeper名字空間中的每一個節點都由其路徑標識。
與標準文件系統不一樣,ZooKeeper名字空間中的每一個節點均可以有關聯的數據以及子節點。這就像一個容許文件也是目錄的文件系統。 (ZooKeeper設計用於存儲協調數據:狀態信息、配置、位置信息等,因此一般存儲在每一個節點中的數據很小,在字節到千字節範圍內)討論 ZooKeeper數據節點時,咱們用術語znode來明確指示。
Znode會維護一個stat結構體,其中包含數據和ACL的版本號與時間戳,以便於進行緩存驗證和協調更新。每次修改znode數據時,版本號會增加。客戶端獲取數據的時候,也同時獲取數據的版本。
對znode數據的讀寫操做是原子的。讀取操做獲取節點的全部數據,寫入操做替換全部數據。節點的訪問控制列表(ACL)控制能夠進行操做的用戶。
ZooKeeper具備臨時節點的概念。只要建立節點的會話是活動的,臨時節點就存在。一旦會話終止,臨時節點會被刪除。臨時節點對於實現tbd是頗有用的。
ZooKeeper支持觀察的概念。客戶端能夠在znode上設置觀察。觀察將在znode修改時被觸發和移除。觀察被觸發時客戶端會收到一個數據包,指示znode已經被修改。若是與ZooKeeper服務之間的鏈接斷開,客戶端會收到一個本地通知。這可用於tbd。
ZooKeeper很是高效和簡單。基於其目標:成爲構建如同步這樣的更復雜服務的基礎,ZooKeeper提供下述保證:
l 順序一致性:客戶端的更新將以請求發送的次序被應用。
l 原子性:更新要麼成功,要麼失敗,沒有部分更新。
l 單一系統鏡像:不管鏈接到哪一個服務器,客戶端將看到同樣的視圖。
l 可靠性:更新操做的結果將是持續的,直到客戶端覆蓋了更新。
l 及時性:在某個時間範圍內,客戶端視圖確保是最新的。
關於這些保證的詳細信息,以及如何使用這些保證,請參看tbd。
ZooKeeper的設計目標之一是提供很是簡單的編程接口。ZooKeeper僅支持這些操做:
l create:在樹中某位置建立一個節點。
l delete:刪除一個節點。
l exists:測試某位置是否存在某節點。
l get data:讀取節點數據。
l set data:向節點寫入數據。
l get children:獲取子節點列表。
l sync:等待數據傳播。
關於這些操做的更深刻討論,以及如何使用它們來實現更高層的操做,請參看tbd。
下圖顯示了ZooKeeper服務的高層組件。除了請求處理器(Request Processor)以外,組成ZooKeeper服務的每一個服務器擁有每一個組件的自有拷貝。
自我複製數據庫(replicated database)是一個包含整個數據樹的內存數據庫。更新會記錄到磁盤中以即可以恢復,而且將寫操做應用到內存數據庫以前會先寫入到磁盤。
每一個ZooKeeper服務器都爲客戶服務。客戶端鏈接到一個服務器,提交請求。讀請求由每一個服務器數據庫的本地拷貝進行服務。改變服務狀態的請求和寫請求由一致性協議處理。
做爲一致性協議的一部分,客戶端的全部寫請求都被轉發到單個服務器,也就是領導者。其餘ZooKeeper服務器則是跟隨者,它們接收來自領導者的建議,對傳遞的消息達成一致。消息層考慮了替換失敗的領導者和跟隨者與領導者同步的問題。
ZooKeeper使用定製的原子消息協議。由於消息層是原子的,ZooKeeper可保證本地拷貝不會發散(diverge)。收到寫請求時,領導者計算寫入操做後系統的狀態,將其轉換成一個捕獲此狀態的事務。
ZooKeeper的編程接口很是簡單。可是,可將其用於實現高層順序操做,如同步原語、組成員管理、全部者關係管理等。更多信息請參看tbd。
ZooKeeper被設計爲高性能的。但它真的是高性能的嗎?Yahoo研究中心的ZooKeeper開發團隊證明了ZooKeeper的高性能,特別是在讀操做比寫操做多的應用中(見下圖),由於寫操做涉及在全部服務器間同步狀態。(讀操做比寫操做可能是協調服務的典型狀況)
上圖是ZooKeeper 3.2在配置有兩個2GHz Xeon處理器和兩個SATA 15K RPM驅動器的服務器上運行時的吞吐率圖形。一個驅動器配置爲ZooKeeper日誌專用設備。快照寫入到操做系統驅動器。讀寫操做1KB的數據。「服務器數」指的是ZooKeeper集羣的大小,即組成服務的服務器個數。大約30個其餘服務器用於模擬客戶端。ZooKeeper集羣配置爲不容許客戶端鏈接到領導者。
提示:3.2版的讀寫性能是3.1版的2倍。
Benchmarks也代表ZooKeeper是可靠的。下圖(第10節的圖)顯示了ZooKeeper在各類失敗狀況下的反應。圖中標記的各個事件是:
1.跟隨者失敗和恢復
2.另外一個跟隨者失敗和恢復
3.領導者失敗
4.兩個跟隨者失敗和恢復
5.另外一個領導者失敗
爲揭示在有失敗注入時系統的行爲,咱們在一個由7臺機器組成的ZooKeeper服務上運行和先前同樣的benchmark測試,可是讓寫操做的百分比固定爲30%,這是預期負載比例的保守估計。
此圖有幾處值得仔細觀察。首先,若是跟隨者失敗後快速恢復,則ZooKeeper能夠維持高吞吐率。但更重要的是,領導者選舉算法讓系 統能夠足夠快地恢復,以阻止吞吐率有實質性的降低。據咱們觀察,ZooKeeper選舉一個新的領導者的時間小於200ms。第三,一旦跟隨者恢復而且開 始處理請求,ZooKeeper能夠恢復高吞吐率。
ZooKeeper已經在不少工業應用中成功使用。 Yahoo!在Yahoo! Message Broker中使用ZooKeeper做爲協調和故障恢復服務。 Yahoo! Message Broker是一個高度擴展的發佈-訂閱系統,管理着成千上萬個須要拷貝和數據傳遞的話題。Yahoo!的不少廣告系統也 使用ZooKeeper來實現可靠服務。
咱們鼓勵用戶和開發者加入社區,貢獻技能。更多信息請看Apache的ZooKeeper工程。