ZooKeeper系列文章:http://www.javashuo.com/article/p-waqydwdc-bt.htmlhtml
ZooKeeper是一個開源的爲分佈式應用提供分佈式協調的服務。它公開了一組簡單的原語,分佈式應用程序能夠基於這些原語實現更高級別的服務,包括同步、維護配置、組和命名。它的設計易於編程,它使用一個遵循文件系統中常見的目錄樹結構的數據模型。它在Java環境中運行,對Java和C都有綁定。node
協調服務是出了名的難。它們特別容易出錯,如競態條件和死鎖。ZooKeeper背後的動機是讓分佈式應用從零開始實現一站式協調服務。數據庫
ZooKeeper很簡單。經過共享一個相似於標準文件系統結構的層次名稱空間,Zookeeper容許分佈式進程進行各自的協調。名稱空間中包含了註冊數據——即所謂的znodes,它們相似於文件和目錄。Zookeeper不像文件系統,目的是數據存儲,Zookeeper的數據存放在內存中,這意味着zookeeper具備高吞吐量和低延遲的優勢。編程
ZooKeeper很是注重高性能、高可用性、嚴格有序的訪問。ZooKeeper的性能方面意味着它能夠在大型分佈式系統中使用。可靠性方面使它不會出現單點故障。嚴格有序意味着能夠在客戶端實現複雜的同步原語。api
ZooKeeper是複製的。與它所協調的分佈式進程同樣,ZooKeeper自己也打算在一組主機上進行復制。緩存
組成ZooKeeper的每一個server之間都必須互相瞭解。每一個server都維護狀態信息(state)的內存映像,以及持久存儲中的事務日誌和快照。只要ZooKeeper中的大多數server可用,ZooKeeper服務就可用。session
每一個client鏈接到ZooKeeper集羣中的某個server。客戶端會與之創建TCP鏈接,經過該TCP鏈接來發送請求、獲取響應、獲取觀察事件(watch events)以及發送心跳。若是TCP鏈接中斷,客戶端將鏈接到另外一個server。分佈式
ZooKeeper是有序的。ZooKeeper給每次更新都貼上一個數字,這個數字反映了全部ZooKeeper事務的順序。後續操做可使用這個順序來實現高級抽象,例如同步原語。性能
ZooKeeper速度很快,特別是在"以讀爲主"的工做負載中尤爲快速。ZooKeeper應用程序可用在數千臺機器上運行,在多讀少寫(比率在10:1左右)的環境中表現最好。測試
ZooKeeper提供的名稱空間很是相似於標準文件系統。名稱是由斜線(/)分隔的路徑元素序列。在ZooKeeper名稱空間中的每個節點都是經過一條路徑來標識的。
與標準文件系統不一樣的是,ZooKeeper名稱空間中的每一個節點(路徑)均可以有與之關聯的數據,子節點也如此(譯註:即節點的路徑自身攜帶數據)。這就像是一個既文件也目錄的文件系統。(ZooKeeper的目的是存儲協調數據:狀態信息、配置、位置信息等,因此每一個節點存儲的數據一般都很小,通常都是kb級別的)。咱們使用術語znode來明確說明咱們正在討論ZooKeeper數據節點。
znode維護一個包含數據更改版本號、ACL更改版本號和時間戳版本號的stat結構,以便可以作緩存驗證和協調更新。每當znode的數據發生變化,版本號就會增長。例如,客戶端每次檢索數據的同時,也會接收數據的版本信息。
名稱空間中,每一個znode上存儲的數據的讀、寫操做都是原子性的。讀操做會獲取與znode關聯的全部數據,寫操做會替換全部數據。每一個節點都有一個訪問控制列表(ACL),限制誰能夠作什麼。
ZooKeeper也有臨時節點(ephemeral nodes)的概念。只要建立這些znode的會話(session)是活動的,這些znode就存在。當會話結束時,znode被刪除。當您想要實現[tbd]時,臨時節點很是有用。
ZooKeeper支持觀察(watch)的概念。客戶端能夠在znode上設置一個watch。當znode更改時,將觸發並刪除一個watch。當watch被觸發時,客戶端會收到一個通知znode已更改的數據包。若是客戶端和ZooKeeper server之間的TCP鏈接中斷了,客戶端將收到本地通知。這些可用於[tbd]。
ZooKeeper快速又簡單。但因爲它的目標是做爲構建更復雜服務(如同步)的基礎,因此它要實現一些保證。包括:
更多信息,以及如何使用它們,請參見[tbd]。
ZooKeeper的一個設計目標是提供很是簡單的編程接口。所以,它只支持如下幾個操做:
create
:在樹中的某個位置建立一個節點。delete
:刪除一個節點。exists
:測試一個節點是否存在。get data
:讀取節點數據。set data
:向節點中寫入數據。get children
:檢索某節點的子節點列表。sync
:等待要傳播的數據。更深刻內容,以及如何使用它們實現更高級別的操做,請參閱[tbd]。
下圖顯示了ZooKeeper服務的高層組件。除了request processor,構成ZooKeeper Service的每一個server都複製本身的每一個組件副本。
replicated database是包含整個數據樹(data tree)的內存數據庫。每次發起的更新都會將其記錄到磁盤中的日誌,以便之後可以進行恢復(recovery),在更新真正應用到內存數據庫以前,還會先將更新序列化到磁盤中。
每一個ZooKeeper server都會爲客戶端提供服務。客戶端鏈接到一個server來提交request。對於read request,每一個server會從本地database的副本中提供服務。對於write request,這些請求會更改服務狀態,它們由協商協議(agreement procotol)來處理。
做爲協商協議(agreement procotol)的一部分,全部來自客戶端的write request都被轉發到一個稱爲leader的server上。ZooKeeper中的其它server,都稱爲follower,它們接收來自leader的消息,並傳遞那些達成一致的消息。消息層(messaging layer)負責在leader故障時選舉新的leader,並剩餘的follower和新的leader保持同步。
ZooKeeper使用一個自定義的原子消息傳遞協議。因爲該消息層是原子性的,ZooKeeper能夠保證本地副本永遠不會出現分歧。當leader收到write request時,它會計算當寫操做被執行時系統狀態,並將其轉換爲帶有該狀態的事務。
ZooKeeper的編程接口很簡單。但有了它,您能夠實現更高級的操做,好比同步原語、組成員關係(group membership)、全部權(ownership)等等。更多信息請參閱[tbd]。
ZooKeeper具備高性能。真的如此嗎?雅虎ZooKeeper的開發團隊的研究結果已經代表確實如此。(參見下圖)。當讀操做比寫操做更頻繁時,ZooKeeper的性能很是高,由於寫操做會調用全部節點的狀態同步。(協調服務的典型狀況就是多讀少寫)。
注意:在3.2版本中,r/w的性能比3.1版本提升了大約2倍。