前言
相信大家對 ZooKeeper 應該不算陌生。但是你真的瞭解 ZooKeeper 是個什麼東西嗎?如果別人/面試官讓你給他講講 ZooKeeper 是個什麼東西,你能回答到什麼地步呢?
我本人曾經使用過 ZooKeeper 作為 Dubbo 的註冊中心,另外在搭建 solr 叢集的時候,我使用到了 ZooKeeper 作為 solr 叢集的管理工具。前幾天,總結專案經驗的時候,我突然問自己 ZooKeeper 到底是個什麼東西?想了半天,腦海中只是簡單的能浮現出幾句話:“①Zookeeper 可以被用作註冊中心。 ②Zookeeper 是 Hadoop 生態系統的一員;③構建 Zookeeper 叢集的時候,使用的伺服器最好是奇數臺。” 可見,我對於 Zookeeper 的理解僅僅是停留在了錶面。
所以,透過本文,希望帶大家稍微詳細的瞭解一下 ZooKeeper 。如果沒有學過 ZooKeeper ,那麼本文將會是你進入 ZooKeeper 大門的墊腳磚。如果你已經接觸過 ZooKeeper ,那麼本文將帶你回顧一下 ZooKeeper 的一些基礎概念。
最後,本文只涉及 ZooKeeper 的一些概念,並不涉及 ZooKeeper 的使用以及 ZooKeeper 叢集的搭建。 網上有介紹 ZooKeeper 的使用以及搭建 ZooKeeper 叢集的文章,大家有需要可以自行查閱。
一 什麼是 ZooKeeper
ZooKeeper 的由來
下麵這段內容摘自《從Paxos到Zookeeper 》第四章第一節的某段內容,推薦大家閱讀以下:
Zookeeper最早起源於雅虎研究院的一個研究小組。在當時,研究人員發現,在雅虎內部很多大型系統基本都需要依賴一個類似的系統來進行分散式協調,但是這些系統往往都存在分散式單點問題。所以,雅虎的開發人員就試圖開發一個通用的無單點問題的分散式協調框架,以便讓開發人員將精力集中在處理業務邏輯上。
關於“ZooKeeper”這個專案的名字,其實也有一段趣聞。在立項初期,考慮到之前內部很多專案都是使用動物的名字來命名的(例如著名的Pig專案),雅虎的工程師希望給這個專案也取一個動物的名字。時任研究院的首席科學家RaghuRamakrishnan開玩笑地說:“在這樣下去,我們這兒就變成動物園了!”此話一齣,大家紛紛表示就叫動物園管理員吧一一一因為各個以動物命名的分散式元件放在一起,雅虎的整個分散式系統看上去就像一個大型的動物園了,而Zookeeper正好要用來進行分散式環境的協調一一於是,Zookeeper的名字也就由此誕生了。
1.1 ZooKeeper 概覽
ZooKeeper 是一個開源的分散式協調服務,ZooKeeper框架最初是在“Yahoo!”上構建的,用於以簡單而穩健的方式訪問他們的應用程式。 後來,Apache ZooKeeper成為Hadoop,HBase和其他分散式框架使用的有組織服務的標準。 例如,Apache HBase使用ZooKeeper跟蹤分散式資料的狀態。ZooKeeper 的設計標的是將那些複雜且容易出錯的分散式一致性服務封裝起來,構成一個高效可靠的原語集,並以一系列簡單易用的介面提供給使用者使用。
原語: 作業系統或計算機網路用語範疇。是由若干條指令組成的,用於完成一定功能的一個過程。具有不可分割性·即原語的執行必須是連續的,在執行過程中不允許被中斷。
ZooKeeper 是一個典型的分散式資料一致性解決方案,分散式應用程式可以基於 ZooKeeper 實現諸如資料釋出/訂閱、負載均衡、命名服務、分散式協調/通知、叢集管理、Master 選舉、分散式鎖和分散式佇列等功能。
Zookeeper 一個最常用的使用場景就是用於擔任服務生產者和服務消費者的註冊中心。 服務生產者將自己提供的服務註冊到Zookeeper中心,服務的消費者在進行服務呼叫的時候先到Zookeeper中查詢服務,獲取到服務生產者的詳細資訊之後,再去呼叫服務生產者的內容與資料。如下圖所示,在 Dubbo架構中 Zookeeper 就擔任了註冊中心這一角色。
1.2 結合個人使用情況的講一下 ZooKeeper
在我自己做過的專案中,主要使用到了 ZooKeeper 作為 Dubbo 的註冊中心(Dubbo 官方推薦使用 ZooKeeper註冊中心)。另外在搭建 solr 叢集的時候,我使用 ZooKeeper 作為 solr 叢集的管理工具。這時,ZooKeeper 主要提供下麵幾個功能:1、叢集管理:容錯、負載均衡。2、配置檔案的集中管理3、叢集的入口。
我個人覺得在使用 ZooKeeper 的時候,最好是使用 叢集版的 ZooKeeper 而不是單機版的。官網給出的架構圖就描述的是一個叢集版的 ZooKeeper 。通常 3 臺伺服器就可以構成一個 ZooKeeper 叢集了。
為什麼最好使用奇數臺伺服器構成 ZooKeeper 叢集?
所謂的zookeeper容錯是指,當宕掉幾個zookeeper伺服器之後,剩下的個數必須大於宕掉的個數的話整個zookeeper才依然可用。假如我們的叢集中有n臺zookeeper伺服器,那麼也就是剩下的服務數必須大於n/2。先說一下結論,2n和2n-1的容忍度是一樣的,都是n-1,大家可以先自己仔細想一想,這應該是一個很簡單的數學問題了。 比如假如我們有3臺,那麼最大允許宕掉1臺zookeeper伺服器,如果我們有4臺的的時候也同樣只允許宕掉1臺。 假如我們有5臺,那麼最大允許宕掉2臺zookeeper伺服器,如果我們有6臺的的時候也同樣只允許宕掉2臺。
綜上,何必增加那一個不必要的zookeeper呢?
二 關於 ZooKeeper 的一些重要概念
2.1 重要概念總結
-
ZooKeeper 本身就是一個分散式程式(只要半數以上節點存活,ZooKeeper 就能正常服務)。
-
為了保證高可用,最好是以叢集形態來部署 ZooKeeper,這樣只要叢集中大部分機器是可用的(能夠容忍一定的機器故障),那麼 ZooKeeper 本身仍然是可用的。
-
ZooKeeper 將資料儲存在記憶體中,這也就保證了 高吞吐量和低延遲(但是記憶體限制了能夠儲存的容量不太大,此限制也是保持znode中儲存的資料量較小的進一步原因)。
-
ZooKeeper 是高效能的。 在“讀”多於“寫”的應用程式中尤其地高效能,因為“寫”會導致所有的伺服器間同步狀態。(“讀”多於“寫”是協調服務的典型場景。)
-
ZooKeeper有臨時節點的概念。 當建立臨時節點的客戶端會話一直保持活動,瞬時節點就一直存在。而當會話終結時,瞬時節點被刪除。持久節點是指一旦這個ZNode被建立了,除非主動進行ZNode的移除操作,否則這個ZNode將一直儲存在Zookeeper上。
-
ZooKeeper 底層其實只提供了兩個功能:①管理(儲存、讀取)使用者程式提交的資料;②為使用者程式提交資料節點監聽服務。
下麵關於會話(Session)、 Znode、版本、Watcher、ACL概念的總結都在《從Paxos到Zookeeper 》第四章第一節以及第七章第八節有提到,感興趣的可以看看!
2.2 會話(Session)
Session 指的是 ZooKeeper 伺服器與客戶端會話。在 ZooKeeper 中,一個客戶端連線是指客戶端和伺服器之間的一個 TCP 長連線。客戶端啟動的時候,首先會與伺服器建立一個 TCP 連線,從第一次連線建立開始,客戶端會話的生命週期也開始了。透過這個連線,客戶端能夠透過心跳檢測與伺服器保持有效的會話,也能夠向Zookeeper伺服器傳送請求並接受響應,同時還能夠透過該連線接收來自伺服器的Watch事件通知。 Session的sessionTimeout
值用來設定一個客戶端會話的超時時間。當由於伺服器壓力太大、網路故障或是客戶端主動斷開連線等各種原因導致客戶端連線斷開時,只要在sessionTimeout
規定的時間內能夠重新連線上叢集中任意一臺伺服器,那麼之前建立的會話仍然有效。
在為客戶端建立會話之前,服務端首先會為每個客戶端都分配一個sessionID。由於 sessionID 是 Zookeeper 會話的一個重要標識,許多與會話相關的執行機制都是基於這個 sessionID 的,因此,無論是哪臺伺服器為客戶端分配的 sessionID,都務必保證全域性唯一。
2.3 Znode
在談到分散式的時候,我們通常說的“節點"是指組成叢集的每一臺機器。然而,在Zookeeper中,“節點"分為兩類,第一類同樣是指構成叢集的機器,我們稱之為機器節點;第二類則是指資料模型中的資料單元,我們稱之為資料節點一一ZNode。
Zookeeper將所有資料儲存在記憶體中,資料模型是一棵樹(Znode Tree),由斜槓(/)的進行分割的路徑,就是一個Znode,例如/foo/path1。每個上都會儲存自己的資料內容,同時還會儲存一系列屬性資訊。
在Zookeeper中,node可以分為持久節點和臨時節點兩類。所謂持久節點是指一旦這個ZNode被建立了,除非主動進行ZNode的移除操作,否則這個ZNode將一直儲存在Zookeeper上。而臨時節點就不一樣了,它的生命週期和客戶端會話系結,一旦客戶端會話失效,那麼這個客戶端建立的所有臨時節點都會被移除。另外,ZooKeeper還允許使用者為每個節點新增一個特殊的屬性:SEQUENTIAL.一旦節點被標記上這個屬性,那麼在這個節點被建立的時候,Zookeeper會自動在其節點名後面追加上一個整型數字,這個整型數字是一個由父節點維護的自增數字。
2.4 版本
在前面我們已經提到,Zookeeper 的每個 ZNode 上都會儲存資料,對應於每個ZNode,Zookeeper 都會為其維護一個叫作 Stat 的資料結構,Stat中記錄了這個 ZNode 的三個資料版本,分別是version(當前ZNode的版本)、cversion(當前ZNode子節點的版本)和 cversion(當前ZNode的ACL版本)。
2.5 Watcher
Watcher(事件監聽器),是Zookeeper中的一個很重要的特性。Zookeeper允許使用者在指定節點上註冊一些Watcher,並且在一些特定事件觸發的時候,ZooKeeper服務端會將事件通知到感興趣的客戶端上去,該機制是Zookeeper實現分散式協調服務的重要特性。
2.6 ACL
Zookeeper採用ACL(AccessControlLists)策略來進行許可權控制,類似於 UNIX 檔案系統的許可權控制。Zookeeper 定義瞭如下5種許可權。
其中尤其需要註意的是,CREATE和DELETE這兩種許可權都是針對子節點的許可權控制。
三 ZooKeeper 特點
-
順序一致性: 從同一客戶端發起的事務請求,最終將會嚴格地按照順序被應用到 ZooKeeper 中去。
-
原子性: 所有事務請求的處理結果在整個叢集中所有機器上的應用情況是一致的,也就是說,要麼整個叢集中所有的機器都成功應用了某一個事務,要麼都沒有應用。
-
單一系統映像 : 無論客戶端連到哪一個 ZooKeeper 伺服器上,其看到的服務端資料模型都是一致的。
-
可靠性: 一旦一次更改請求被應用,更改的結果就會被持久化,直到被下一次更改改寫。
四 ZooKeeper 設計標的
4.1 簡單的資料模型
ZooKeeper 允許分散式行程透過共享的層次結構名稱空間進行相互協調,這與標準檔案系統類似。 名稱空間由 ZooKeeper 中的資料暫存器組成 - 稱為znode,這些類似於檔案和目錄。 與為儲存設計的典型檔案系統不同,ZooKeeper資料儲存在記憶體中,這意味著ZooKeeper可以實現高吞吐量和低延遲。
4.2 可構建叢集
為了保證高可用,最好是以叢集形態來部署 ZooKeeper,這樣只要叢集中大部分機器是可用的(能夠容忍一定的機器故障),那麼zookeeper本身仍然是可用的。 客戶端在使用 ZooKeeper 時,需要知道叢集機器串列,透過與叢集中的某一臺機器建立 TCP 連線來使用服務,客戶端使用這個TCP連結來傳送請求、獲取結果、獲取監聽事件以及傳送心跳包。如果這個連線異常斷開了,客戶端可以連線到另外的機器上。
ZooKeeper 官方提供的架構圖:
上圖中每一個Server代表一個安裝Zookeeper服務的伺服器。組成 ZooKeeper 服務的伺服器都會在記憶體中維護當前的伺服器狀態,並且每臺伺服器之間都互相保持著通訊。叢集間透過 Zab 協議(Zookeeper Atomic Broadcast)來保持資料的一致性。
4.3 順序訪問
對於來自客戶端的每個更新請求,ZooKeeper 都會分配一個全域性唯一的遞增編號,這個編號反應了所有事務操作的先後順序,應用程式可以使用 ZooKeeper 這個特性來實現更高層次的同步原語。 這個編號也叫做時間戳——zxid(Zookeeper Transaction Id)
4.4 高效能
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 機器可以在不影響寫效能的情況下提升叢集的讀效能。
當 Leader 伺服器出現網路中斷、崩潰退出與重啟等異常情況時,ZAB 協議就會進人恢復樣式並選舉產生新的Leader伺服器。這個過程大致是這樣的:
-
Leader election(選舉階段):節點在一開始都處於選舉階段,只要有一個節點得到超半數節點的票數,它就可以當選準 leader。
-
Discovery(發現階段):在這個階段,followers 跟準 leader 進行通訊,同步 followers 最近接收的事務提議。
-
Synchronization(同步階段):同步階段主要是利用 leader 前一階段獲得的最新提議歷史,同步叢集中所有的副本。同步完成之後 準 leader 才會成為真正的 leader。
-
Broadcast(廣播階段) :到了這個階段,Zookeeper 叢集才能正式對外提供事務服務,並且 leader 可以進行訊息廣播。同時如果有新的節點加入,還需要對新節點進行同步。
六 ZooKeeper &ZAB; 協議&Paxos;演演算法
6.1 ZAB 協議&Paxos;演演算法
Paxos 演演算法應該可以說是 ZooKeeper 的靈魂了。但是,ZooKeeper 並沒有完全採用 Paxos演演算法 ,而是使用 ZAB 協議作為其保證資料一致性的核心演演算法。另外,在ZooKeeper的官方檔案中也指出,ZAB協議並不像 Paxos 演演算法那樣,是一種通用的分散式一致性演演算法,它是一種特別為Zookeeper設計的崩潰可恢復的原子訊息廣播演演算法。
6.2 ZAB 協議介紹
ZAB(ZooKeeper Atomic Broadcast 原子廣播) 協議是為分散式協調服務 ZooKeeper 專門設計的一種支援崩潰恢復的原子廣播協議。 在 ZooKeeper 中,主要依賴 ZAB 協議來實現分散式資料一致性,基於該協議,ZooKeeper 實現了一種主備樣式的系統架構來保持叢集中各個副本之間的資料一致性。
6.3 ZAB 協議兩種基本的樣式:崩潰恢復和訊息廣播
ZAB協議包括兩種基本的樣式,分別是 崩潰恢復和訊息廣播。當整個服務框架在啟動過程中,或是當 Leader 伺服器出現網路中斷、崩潰退出與重啟等異常情況時,ZAB 協議就會進人恢復樣式並選舉產生新的Leader伺服器。當選舉產生了新的 Leader 伺服器,同時叢集中已經有過半的機器與該Leader伺服器完成了狀態同步之後,ZAB協議就會退出恢復樣式。其中,所謂的狀態同步是指資料同步,用來保證叢集中存在過半的機器能夠和Leader伺服器的資料狀態保持一致。
當叢集中已經有過半的Follower伺服器完成了和Leader伺服器的狀態同步,那麼整個服務框架就可以進人訊息廣播樣式了。 當一臺同樣遵守ZAB協議的伺服器啟動後加人到叢集中時,如果此時叢集中已經存在一個Leader伺服器在負責進行訊息廣播,那麼新加人的伺服器就會自覺地進人資料恢復樣式:找到Leader所在的伺服器,並與其進行資料同步,然後一起參與到訊息廣播流程中去。正如上文介紹中所說的,ZooKeeper設計成只允許唯一的一個Leader伺服器來進行事務請求的處理。Leader伺服器在接收到客戶端的事務請求後,會生成對應的事務提案併發起一輪廣播協議;而如果叢集中的其他機器接收到客戶端的事務請求,那麼這些非Leader伺服器會首先將這個事務請求轉發給Leader伺服器。
關於 ZAB 協議&Paxos;演演算法 需要講和理解的東西太多了,說實話,筆主到現在不太清楚這倆兄弟的具體原理和實現過程。推薦閱讀下麵兩篇文章:
-
圖解 Paxos 一致性協議:
http://blog.xiaohansong.com/2016/09/30/Paxos/
-
Zookeeper ZAB 協議分析:
http://blog.xiaohansong.com/2016/08/25/zab/
關於如何使用 zookeeper 實現分散式鎖,可以檢視下麵這篇文章:
-
Zookeeper ZAB 協議分析:
https://blog.csdn.net/qiangcuo6087/article/details/79067136
六 總結
透過閱讀本文,想必大家已從
-
ZooKeeper的由來 。
-
ZooKeeper 到底是什麼 。
-
ZooKeeper 的一些重要概念(會話(Session)、 Znode、版本、Watcher、ACL)
-
ZooKeeper 的特點。
-
ZooKeeper 的設計標的。
-
ZooKeeper 叢集角色介紹 (Leader、Follower 和 Observer 三種角色)
-
ZooKeeper &ZAB; 協議&Paxos;演演算法。
這七點瞭解了 ZooKeeper 。
參考
-
《從Paxos到Zookeeper 》
-
https://cwiki.apache.org/confluence/display/ZOOKEEPER/ProjectDescription
-
https://cwiki.apache.org/confluence/display/ZOOKEEPER/Index
-
https://www.cnblogs.com/raphael5200/p/5285583.html
-
https://zhuanlan.zhihu.com/p/30024403
●編號789,輸入編號直達本文
●輸入m獲取文章目錄
演演算法與資料結構
更多推薦《18個技術類公眾微信》
涵蓋:程式人生、演演算法與資料結構、駭客技術與網路安全、大資料技術、前端開發、Java、Python、Web開發、安卓開發、iOS開發、C/C++、.NET、Linux、資料庫、運維等。