ZooKeeper:分佈式應用的分佈協調服務html
ZooKeeper是一個爲分佈式應用提供的分佈的開源的協調服務。它暴露一組簡單的原子操做,分佈式系統能夠在這之上爲同步,配置管理,和組和命名實現更高級的服務。它被設計來編程簡單,而且使用一個跟文件系統類似的數據模型。它在Java中運行而且綁定Java和C。node
協調服務衆所周知地很是難正確。它們特別易於競爭條件和死鎖的錯誤。ZooKeeper後面的動機是減輕分佈式應用數據庫
從頭開始實現協調服務的責任。apache
設計目標編程
ZooKeeper是簡單的。ZooKeeper容許分佈式的進程彼此協調經過一個共享的結構化的命名空間,這個命名空間組織結構和標準的文件系統類似。這個命名空間包括數據註冊器 - 稱爲znodes,用ZooKeeper的說話 - 而且他們和文件和文件夾類似。和典型的文件系統設計用來存儲不一樣的是,ZooKeeper的數據保存在內存中,這意爲着ZooKeeper能夠達到很高的吞吐量和低延遲。緩存
ZooKeeper實現給高性能,高可用,嚴格的順序訪問增長了一個保險。ZooKeeper的高性能方面意爲着它能夠被用在大的分佈式系統。可靠性避免它成爲一個失敗單點。嚴格的訪問順序意爲複雜的同步原語能夠在客戶端實現。服務器
ZooKeeper是可複製的。和它協調的分佈的進程同樣,ZooKeeper自己也打算是可複製的經過一組稱爲集羣的主機。數據結構
ZooKeeper Service分佈式
組成ZooKeeper的服務的服務器必須都知道彼此。他們維護一個在內存中的狀態鏡像,和一個事務日誌和一個持久存儲中的快照。只要大多數是可用的,ZooKeeper服務就是可用的。性能
客戶端鏈接到一個單獨的ZooKeeper服務器。客戶端維護一個TCP鏈接,經過這個連接它發送請求,獲取響應,獲取watch事件,而且發送心跳。若是到服務器的TCP鏈接中斷,客戶端將連到另外一個不一樣的服務器。
ZooKeeper是有序的。ZooKeeper用一個數字來記錄每一次更新,這個數字反映了全部ZooKeeper事務的順序,隨後的操做可能使用這個順序來實現 更高級的抽象,好比同步原語
ZooKeeper是快速的。它至關的快在讀爲主的工做場景中。ZooKeeper應用運行在成千上萬個機器上,而且它表現很好在讀比寫廣泛的,比例大約10:1的時候。
數據模型和分層次的命名空間
ZooKeeper提供的命名空間很是像一個標準的文件系統。一個名字是一系列的被/分開的路徑元素,在ZooKeeper中每個節點被標示爲一個路徑。
ZooKeeper's Hierarchical Namespace
節點和短暫的節點
和標準的文件系統不一樣,每個ZooKeeper中的節點能夠有數據和它關聯,子節點也同樣。就像一個文件系統容許一個文件是一個目錄。(ZooKeeper被設計用來存儲協調數據:狀態信息,配置,地址信息,等等。因此存儲在每個節點的數據一般很小,在字節和千字節的範圍。)咱們使用znode來使咱們清楚咱們正在討論ZooKeeper的數據節點。
Znodes維護一個數據結構包括數據改變,ACL改變,的版本號和時間戳,來容許緩存檢驗和協調更新。每次一個znode的數據改變,版本號增長。例如,當客戶端檢索數據,它也收到數據的版本。
在命名空間裏的每個節點存儲的數據原子地讀和寫。讀獲得一個znode關聯的全部的數據字節,而且寫替換全部的數據。每個節點有一個訪問控制列表(ACL)來限制誰能作和作什麼。
ZooKeeper也有短暫節點的概念。這些節點存在只要建立它們的會話是活躍的。當會話結束,這個節點也就被刪除。短暫的節點是有用的當你想實現[tbd]。
條件更新和監視器
ZooKeeper支持監視的概念,客戶端能夠在znode上設置一個監視器,監視器將被觸發和刪除當znode改變的時候。當監視器被觸發的時候,客戶端收到一個數據包說明znode已經被改變。而且若是客戶端和zookeeper服務器之間的連接已經斷掉,客戶端將會收到一個本地的通知,這些能夠被用來實現tbd.
擔保
ZooKeeper是很是快和簡單的。儘管它的目標是構建例如同步這樣更復雜服務的基礎,它提供了一組保證它們是:
有關這些的更多信息,而且它們怎麼被使用,參考[tbd]
簡單的API
ZooKeeper的其中一個設計目標就是提供一個簡單的編程接口,做爲結果,它只提供了這些操做:
create
在樹的一個位置上建立一個節點
delete
刪除一個節點
exists
檢驗一個節點是否在這個位置
get data
從節點讀取數據
set data
往節點寫數據
get children
檢索一個節點的孩子節點列表
sync
等待數據被傳播
對於這些更深刻的討論,和他們怎麼被用來實現更高級的操做,請參考[tbd]
實現
ZooKeeper Components展現了ZooKeepere服務更高級的組件,除了請求處理器,每一個組成ZooKeeper服務的服務器上覆制本身的每一個組件的副本。
ZooKeeper Components
複製的數據庫是一個內存數據庫,包含了整個數據樹。更新被記錄到硬盤爲了恢復。而且寫操做被序列化到磁盤上在它應用到內存數據訓以前。
每個ZooKeeper服務器給客戶端提供服務,客戶端連到其中一個服務器來提交請求。請請求被每個服務器的數據庫的本地副本提供服務。改變服務器狀態的請求,寫請求,被一致協議處理。
做爲一致性協議的一部分,全部從客戶端來的寫請求被推送到一個服務器,就是所謂的領導者。剩下的其它ZooKeeper服務器,就是追隨者,它們從領導者接收消息提議,並贊成消息傳遞。消息層負責更換失效的領導者而且同步領導者和追隨者。
ZooKeeper使用自定義的原子消息協議。由於消息層是原子的,ZooKeeper能夠保證本地複製永遠不會出現分歧。當領導者收到一個寫請求,它計算當更新被應用時系統處於怎麼狀態,而且轉換這個請求爲到一個事務中來捕獲這個狀態。
使用
ZooKeeper的編程接口至關簡單,利用它你能夠實現更高級的順序操做,例如同步原語,羣成員管理,全部權,等待。一些分佈式系統已經使用它來[],更多信息,參考[tbd]。
性能
ZooKeeper是設計爲了高性能的。可是是真的麼?來自Yahoo! Research的ZooKeeper的開發團隊的結果表示它是(參考ZooKeeper Throughput as the Read-Write Ratio Varies.)。在讀比寫多的應用中它有更高的性能,由於寫涉及同步全部全部服務器的狀態。
ZooKeeper Throughput as the Read-Write Ratio Varies
圖片ZooKeeper Throughput as the Read-Write Ratio Varies是一個運行在dual 2Ghz Xeon和兩個15K轉的SATA驅動器的3.2版本的ZooKeeper的吞吐圖。其中一個驅動器專門用來做爲ZooKeeper的日誌記錄設備,快照被寫入到系統驅動器。寫請求是1k讀請求也是1k."Servers"表示ZooKeeper集羣的數量,組成服務的服務器數量。大概30個其它有服務器用來模擬客戶端。這個ZooKeeper被配置成領導者不容許和客戶端相連。
注意:
3.2版本的讀寫性能相比之3.1版本的性能提升了大約2倍
基準測試也表示了它是可靠的。Reliability in the Presence of Errors展現了若是對各類故障作出響應。圖片中標記的事件是下面這些:
1. 追隨者的失效和恢復。
2. 不一樣的追隨都的失效和恢復。
3. 領導者的失效
4. 兩個追隨者的失效和恢復
5. 另外一個領導者的失效
可靠性
爲了展現系統隨着時間注入失敗的的行爲,咱們運行了一個7臺機器組成 的ZooKeeper的服務。咱們以前運行過這個基準測試。可是此次咱們保持寫的比例在30%,這是咱們指望的工做負荷的保守比例。
Reliability in the Presence of Errors
從這個圖中能夠看到幾個重要言論。首先,若是追隨者失效而且很快地恢復,ZooKeeper能夠維持一個高的吞吐量儘管有失效。可是也許更重要的是。領導者的選舉邏輯容許系統很快地恢復來避免吞吐量降低的太厲害。在咱們的觀察中,ZooKeeper消耗低於200ms來選出一個新領導者。當追隨者恢復,ZooKeeper能夠再次提高吞吐量一旦它們再次處理請求。
ZooKeeper已經成功地應用在不少工業應用中。它在Yahoo!爲Yahoo!的Message Broker做爲協調和失效恢復服務來使用。它是一個高度可擴展的發佈訂閱系統管理者成千上萬個主題爲了複製和數據傳遞。它被用在Yahoo!的Fetech Service,它也管理失效恢復。許多的Yahoo!廣告系統也使用ZooKeeper來實現可靠性服務。