我本人曾經使用過 ZooKeeper 做爲 Dubbo 的註冊中心,另外在搭建 Solr 集羣的時候,我使用到了 ZooKeeper 做爲 Solr 集羣的管理工具。node
前幾天,總結項目經驗的時候,我忽然問本身 ZooKeeper 究竟是個什麼東西?算法
想了半天,腦海中只是簡單的能浮現出幾句話:性能優化
可見,我對於 Zookeeper 的理解僅僅是停留在了表面。因此,經過本文,但願帶你們稍微詳細的瞭解一下 ZooKeeper 。服務器
若是沒有學過 ZooKeeper,那麼本文將會是你進入 ZooKeeper 大門的墊腳磚;若是你已經接觸過 ZooKeeper ,那麼本文將帶你回顧一下 ZooKeeper 的一些基礎概念。網絡
最後,本文只涉及 ZooKeeper 的一些概念,並不涉及 ZooKeeper 的使用以及 ZooKeeper 集羣的搭建。session
網上有介紹 ZooKeeper 的使用以及搭建 ZooKeeper 集羣的文章,你們有須要能夠自行查閱。數據結構
什麼是 ZooKeeper架構
ZooKeeper 的由來併發
下面這段內容摘自《從 Paxos 到 ZooKeeper 》第四章第一節的某段內容,推薦你們閱讀一下:負載均衡
Zookeeper 最先起源於雅虎研究院的一個研究小組。在當時,研究人員發現,在雅虎內部不少大型系統基本都須要依賴一個相似的系統來進行分佈式協調,可是這些系統每每都存在分佈式單點問題。
因此,雅虎的開發人員就試圖開發一個通用的無單點問題的分佈式協調框架,以便讓開發人員將精力集中在處理業務邏輯上。
關於「ZooKeeper」這個項目的名字,其實也有一段趣聞。在立項初期,考慮到以前內部不少項目都是使用動物的名字來命名的(例如著名的Pig項目),雅虎的工程師但願給這個項目也取一個動物的名字。
時任研究院的首席科學家 Raghu Ramakrishnan 開玩笑地說:「在這樣下去,咱們這兒就變成動物園了!」
此話一出,你們紛紛表示就叫動物園管理員吧,由於各個以動物命名的分佈式組件放在一塊兒,雅虎的整個分佈式系統看上去就像一個大型的動物園了。
而 Zookeeper 正好要用來進行分佈式環境的協調,因而,Zookeeper 的名字也就由此誕生了。
ZooKeeper 概覽
ZooKeeper 是一個開源的分佈式協調服務,ZooKeeper 框架最初是在「Yahoo!"上構建的,用於以簡單而穩健的方式訪問他們的應用程序。
後來,Apache ZooKeeper 成爲 Hadoop,HBase 和其餘分佈式框架使用的有組織服務的標準。
例如,Apache HBase 使用 ZooKeeper 跟蹤分佈式數據的狀態。
ZooKeeper 的設計目標是將那些複雜且容易出錯的分佈式一致性服務封裝起來,構成一個高效可靠的原語集,並以一系列簡單易用的接口提供給用戶使用。
原語: 操做系統或計算機網絡用語範疇。它是由若干條指令組成的,用於完成必定功能的一個過程。具備不可分割性,即原語的執行必須是連續的,在執行過程當中不容許被中斷。
ZooKeeper 是一個典型的分佈式數據一致性解決方案,分佈式應用程序能夠基於 ZooKeeper 實現諸如數據發佈/訂閱、負載均衡、命名服務、分佈式協調/通知、集羣管理、Master 選舉、分佈式鎖和分佈式隊列等功能。
ZooKeeper 一個最經常使用的使用場景就是用於擔任服務生產者和服務消費者的註冊中心。
服務生產者將本身提供的服務註冊到 ZooKeeper 中心,服務的消費者在進行服務調用的時候先到 ZooKeeper 中查找服務,獲取到服務生產者的詳細信息以後,再去調用服務生產者的內容與數據。
以下圖所示,在 Dubbo 架構中 ZooKeeper 就擔任了註冊中心這一角色。
Dubbo 架構圖
結合我的使用講一下 ZooKeeper
在我本身作過的項目中,主要使用到了 ZooKeeper 做爲 Dubbo 的註冊中心(Dubbo 官方推薦使用 ZooKeeper 註冊中心)。
另外在搭建 Solr 集羣的時候,我使用 ZooKeeper 做爲 Solr 集羣的管理工具。
這時,ZooKeeper 主要提供下面幾個功能:
我我的以爲在使用 ZooKeeper 的時候,最好是使用集羣版的 ZooKeeper 而不是單機版的。
官網給出的架構圖就描述的是一個集羣版的 ZooKeeper 。一般 3 臺服務器就能夠構成一個 ZooKeeper 集羣了。
爲何最好使用奇數臺服務器構成 ZooKeeper 集羣?
咱們知道在 ZooKeeper 中 Leader 選舉算法採用了 Zab 協議。Zab 核心思想是當多數 Server 寫成功,則任務數據寫成功:
既然 3 個或者 4 個 Server,一樣最多容許 1 個 Server 掛掉,那麼它們的可靠性是同樣的。
因此選擇奇數個 ZooKeeper Server 便可,這裏選擇 3 個 Server。
關於 ZooKeeper 的一些重要概念
重要概念總結
關於 ZooKeeper 的一些重要概念:
而當會話終結時,瞬時節點被刪除。持久節點是指一旦這個 ZNode 被建立了,除非主動進行 ZNode 的移除操做,不然這個 ZNode 將一直保存在 Zookeeper 上。
下面關於會話(Session)、 Znode、版本、Watcher、ACL 概念的總結都在《從 Paxos 到 ZooKeeper 》第四章第一節以及第七章第八節有提到,感興趣的能夠看看!
會話(Session)
Session 指的是 ZooKeeper 服務器與客戶端會話。在 ZooKeeper 中,一個客戶端鏈接是指客戶端和服務器之間的一個 TCP 長鏈接。
客戶端啓動的時候,首先會與服務器創建一個 TCP 鏈接,從第一次鏈接創建開始,客戶端會話的生命週期也開始了。
經過這個鏈接,客戶端可以經過心跳檢測與服務器保持有效的會話,也可以向 Zookeeper 服務器發送請求並接受響應,同時還可以經過該鏈接接收來自服務器的 Watch 事件通知。
Session 的 sessionTimeout 值用來設置一個客戶端會話的超時時間。
當因爲服務器壓力太大、網絡故障或是客戶端主動斷開鏈接等各類緣由致使客戶端鏈接斷開時,只要在 sessionTimeout 規定的時間內可以從新鏈接上集羣中任意一臺服務器,那麼以前建立的會話仍然有效。
在爲客戶端建立會話以前,服務端首先會爲每一個客戶端都分配一個 sessionID。
因爲 sessionID 是 Zookeeper 會話的一個重要標識,許多與會話相關的運行機制都是基於這個 sessionID 的。
所以,不管是哪臺服務器爲客戶端分配的 sessionID,都務必保證全局惟一。
Znode
在談到分佈式的時候,咱們一般說的「節點"是指組成集羣的每一臺機器。
然而,在 ZooKeeper 中,「節點"分爲兩類:
ZooKeeper 將全部數據存儲在內存中,數據模型是一棵樹(Znode Tree),由斜槓(/)的進行分割的路徑,就是一個 Znode,例如/foo/path1。每一個上都會保存本身的數據內容,同時還會保存一系列屬性信息。
在 Zookeeper 中,Node 能夠分爲持久節點和臨時節點兩類。所謂持久節點是指一旦這個 ZNode 被建立了,除非主動進行 ZNode 的移除操做,不然這個 ZNode 將一直保存在 ZooKeeper 上。
而臨時節點就不同了,它的生命週期和客戶端會話綁定,一旦客戶端會話失效,那麼這個客戶端建立的全部臨時節點都會被移除。
另外,ZooKeeper 還容許用戶爲每一個節點添加一個特殊的屬性:SEQUENTIAL。
一旦節點被標記上這個屬性,那麼在這個節點被建立的時候,ZooKeeper 會自動在其節點名後面追加上一個整型數字,這個整型數字是一個由父節點維護的自增數字。
版本
在前面咱們已經提到,Zookeeper 的每一個 ZNode 上都會存儲數據,對應於每一個 ZNode,Zookeeper 都會爲其維護一個叫做 Stat 的數據結構。
Stat 中記錄了這個 ZNode 的三個數據版本,分別是:
Watcher
Watcher(事件監聽器),是 ZooKeeper 中的一個很重要的特性。
ZooKeeper 容許用戶在指定節點上註冊一些 Watcher,而且在一些特定事件觸發的時候,ZooKeeper 服務端會將事件通知到感興趣的客戶端上去,該機制是 ZooKeeper 實現分佈式協調服務的重要特性。
ACL
ZooKeeper 採用 ACL(AccessControlLists)策略來進行權限控制,相似於 UNIX 文件系統的權限控制。
ZooKeeper 定義了 5 種權限,以下圖:
其中尤爲須要注意的是,CREATE 和 DELETE 這兩種權限都是針對子節點的權限控制。
ZooKeeper 特色
ZooKeeper 有哪些特色呢?具體以下:
ZooKeeper 設計目標
簡單的數據模型
ZooKeeper 容許分佈式進程經過共享的層次結構命名空間進行相互協調,這與標準文件系統相似。
名稱空間由 ZooKeeper 中的數據寄存器組成,稱爲 Znode,這些相似於文件和目錄。
與爲存儲設計的典型文件系統不一樣,ZooKeeper 數據保存在內存中,這意味着 ZooKeeper 能夠實現高吞吐量和低延遲。
可構建集羣
爲了保證高可用,最好是以集羣形態來部署 ZooKeeper,這樣只要集羣中大部分機器是可用的(可以容忍必定的機器故障),那麼 ZooKeeper 自己仍然是可用的。
客戶端在使用 ZooKeeper 時,須要知道集羣機器列表,經過與集羣中的某一臺機器創建 TCP 鏈接來使用服務。
客戶端使用這個 TCP 連接來發送請求、獲取結果、獲取監聽事件以及發送心跳包。若是這個鏈接異常斷開了,客戶端能夠鏈接到另外的機器上。
ZooKeeper 官方提供的架構圖:
上圖中每個 Server 表明一個安裝 ZooKeeper 服務的服務器。組成 ZooKeeper 服務的服務器都會在內存中維護當前的服務器狀態,而且每臺服務器之間都互相保持着通訊。
集羣間經過 Zab 協議(Zookeeper Atomic Broadcast)來保持數據的一致性。
順序訪問
對於來自客戶端的每一個更新請求,ZooKeeper 都會分配一個全局惟一的遞增編號。
這個編號反應了全部事務操做的前後順序,應用程序可使用 ZooKeeper 這個特性來實現更高層次的同步原語。這個編號也叫作時間戳—zxid(ZooKeeper Transaction Id)。
高性能
ZooKeeper 是高性能的。在「讀」多於「寫」的應用程序中尤爲地高性能,由於「寫」會致使全部的服務器間同步狀態。(「讀」多於「寫」是協調服務的典型場景。)
ZooKeeper 集羣角色介紹
最典型集羣模式:Master/Slave 模式(主備模式)。在這種模式中,一般 Master 服務器做爲主服務器提供寫服務,其餘的 Slave 服務器從服務器經過異步複製的方式獲取 Master 服務器最新的數據提供讀服務。
可是,在 ZooKeeper 中沒有選擇傳統的 Master/Slave 概念,而是引入了Leader、Follower 和 Observer 三種角色。
以下圖所示:
ZooKeeper 集羣中的全部機器經過一個 Leader 選舉過程來選定一臺稱爲 「Leader」 的機器。
Leader 既能夠爲客戶端提供寫服務又能提供讀服務。除了 Leader 外,Follower 和 Observer 都只能提供讀服務。
Follower 和 Observer 惟一的區別在於 Observer 機器不參與 Leader 的選舉過程,也不參與寫操做的「過半寫成功」策略,所以 Observer 機器能夠在不影響寫性能的狀況下提高集羣的讀性能。
ZooKeeper & ZAB 協議 & Paxos 算法
ZAB 協議 & Paxos 算法
Paxos 算法能夠說是 ZooKeeper 的靈魂了。可是,ZooKeeper 並無徹底採用 Paxos 算法 ,而是使用 ZAB 協議做爲其保證數據一致性的核心算法。
另外,在 ZooKeeper 的官方文檔中也指出,ZAB 協議並不像 Paxos 算法那樣,是一種通用的分佈式一致性算法,它是一種特別爲 ZooKeeper 設計的崩潰可恢復的原子消息廣播算法。
ZAB 協議介紹
ZAB(ZooKeeper Atomic Broadcast 原子廣播)協議是爲分佈式協調服務 ZooKeeper 專門設計的一種支持崩潰恢復的原子廣播協議。
在 ZooKeeper 中,主要依賴 ZAB 協議來實現分佈式數據一致性,基於該協議,ZooKeeper 實現了一種主備模式的系統架構來保持集羣中各個副本之間的數據一致性。
ZAB 協議兩種基本的模式
ZAB 協議包括兩種基本的模式,分別是崩潰恢復和消息廣播。
當整個服務框架在啓動過程當中,或是當 Leader 服務器出現網絡中斷、崩潰退出與重啓等異常狀況時,ZAB 協議就會進入恢復模式並選舉產生新的 Leader 服務器。
當選舉產生了新的 Leader 服務器,同時集羣中已經有過半的機器與該 Leader 服務器完成了狀態同步以後,ZAB 協議就會退出恢復模式。
其中,所謂的狀態同步是指數據同步,用來保證集羣中存在過半的機器可以和 Leader 服務器的數據狀態保持一致。
當集羣中已經有過半的 Follower 服務器完成了和 Leader 服務器的狀態同步,那麼整個服務框架就能夠進人消息廣播模式了。
當一臺一樣遵照 ZAB 協議的服務器啓動後加入到集羣中時,若是此時集羣中已經存在一個 Leader 服務器在負責進行消息廣播。
那麼新加入的服務器就會自覺地進人數據恢復模式:找到 Leader 所在的服務器,並與其進行數據同步,而後一塊兒參與到消息廣播流程中去。
正如上文介紹中所說的,ZooKeeper 設計成只容許惟一的一個 Leader 服務器來進行事務請求的處理。
Leader 服務器在接收到客戶端的事務請求後,會生成對應的事務提案併發起一輪廣播協議。
而若是集羣中的其餘機器接收到客戶端的事務請求,那麼這些非 Leader 服務器會首先將這個事務請求轉發給 Leader 服務器。
總結
經過閱讀本文,想必你們已從如下這七點了解了 ZooKeeper:
順便在此給你們推薦一個Java架構方面的交流學習羣:698581634,裏面會分享一些資深架構師錄製的視頻錄像:有Spring,MyBatis,Netty源碼分析,高併發、高性能、分佈式、微服務架構的原理,JVM性能優化這些成爲架構師必備的知識體系,主要針對有工做經驗的Java開發人員提高本身,突破瓶頸,相信你來學習,會有提高和收穫。在這個羣裏會有你須要的內容 朋友們請抓緊時間加入進來吧。