相信大家對 ZooKeeper 應該不算陌生榜揖。但是你真的了解 ZooKeeper 是個什么東西嗎勾哩?如果別人/面試官讓你給他講講 ZooKeeper 是個什么東西,你能回答到什么地步呢举哟?
我本人曾經(jīng)使用過 ZooKeeper 作為 Dubbo 的注冊中心思劳,另外在搭建 solr 集群的時候,我使用到了 ZooKeeper 作為 solr 集群的管理工具妨猩。前幾天潜叛,總結項目經(jīng)驗的時候,我突然問自己 ZooKeeper 到底是個什么東西?想了半天威兜,腦海中只是簡單的能浮現(xiàn)出幾句話:“①Zookeeper 可以被用作注冊中心销斟。 ②Zookeeper 是 Hadoop 生態(tài)系統(tǒng)的一員;③構建 Zookeeper 集群的時候椒舵,使用的服務器最好是奇數(shù)臺票堵。” 可見逮栅,我對于 Zookeeper 的理解僅僅是停留在了表面。
所以窗宇,通過本文措伐,希望帶大家稍微詳細的了解一下 ZooKeeper 。如果沒有學過 ZooKeeper 军俊,那么本文將會是你進入 ZooKeeper 大門的墊腳磚侥加。如果你已經(jīng)接觸過 ZooKeeper ,那么本文將帶你回顧一下 ZooKeeper 的一些基礎概念粪躬。
最后担败,本文只涉及 ZooKeeper 的一些概念,并不涉及 ZooKeeper 的使用以及 ZooKeeper 集群的搭建镰官。?網(wǎng)上有介紹 ZooKeeper 的使用以及搭建 ZooKeeper 集群的文章提前,大家有需要可以自行查閱。
下面這段內容摘自《從Paxos到Zookeeper 》第四章第一節(jié)的某段內容泳唠,推薦大家閱讀以下:
Zookeeper最早起源于雅虎研究院的一個研究小組狈网。在當時,研究人員發(fā)現(xiàn)笨腥,在雅虎內部很多大型系統(tǒng)基本都需要依賴一個類似的系統(tǒng)來進行分布式協(xié)調拓哺,但是這些系統(tǒng)往往都存在分布式單點問題。所以脖母,雅虎的開發(fā)人員就試圖開發(fā)一個通用的無單點問題的分布式協(xié)調框架士鸥,以便讓開發(fā)人員將精力集中在處理業(yè)務邏輯上。
關于“ZooKeeper”這個項目的名字谆级,其實也有一段趣聞烤礁。在立項初期,考慮到之前內部很多項目都是使用動物的名字來命名的(例如著名的Pig項目),雅虎的工程師希望給這個項目也取一個動物的名字肥照。時任研究院的首席科學家RaghuRamakrishnan開玩笑地說:“在這樣下去鸽凶,我們這兒就變成動物園了!”此話一出建峭,大家紛紛表示就叫動物園管理員吧一一一因為各個以動物命名的分布式組件放在一起玻侥,雅虎的整個分布式系統(tǒng)看上去就像一個大型的動物園了,而Zookeeper正好要用來進行分布式環(huán)境的協(xié)調一一于是亿蒸,Zookeeper的名字也就由此誕生了凑兰。
ZooKeeper 是一個開源的分布式協(xié)調服務掌桩,ZooKeeper框架最初是在“Yahoo!"上構建的,用于以簡單而穩(wěn)健的方式訪問他們的應用程序姑食。 后來波岛,Apache ZooKeeper成為Hadoop,HBase和其他分布式框架使用的有組織服務的標準音半。 例如则拷,Apache HBase使用ZooKeeper跟蹤分布式數(shù)據(jù)的狀態(tài)。ZooKeeper 的設計目標是將那些復雜且容易出錯的分布式一致性服務封裝起來曹鸠,構成一個高效可靠的原語集煌茬,并以一系列簡單易用的接口提供給用戶使用。
原語:?操作系統(tǒng)或計算機網(wǎng)絡用語范疇彻桃。是由若干條指令組成的坛善,用于完成一定功能的一個過程。具有不可分割性·即原語的執(zhí)行必須是連續(xù)的邻眷,在執(zhí)行過程中不允許被中斷眠屎。
ZooKeeper 是一個典型的分布式數(shù)據(jù)一致性解決方案,分布式應用程序可以基于 ZooKeeper 實現(xiàn)諸如數(shù)據(jù)發(fā)布/訂閱肆饶、負載均衡改衩、命名服務、分布式協(xié)調/通知驯镊、集群管理燎字、Master 選舉、分布式鎖和分布式隊列等功能阿宅。
Zookeeper 一個最常用的使用場景就是用于擔任服務生產(chǎn)者和服務消費者的注冊中心候衍。?服務生產(chǎn)者將自己提供的服務注冊到Zookeeper中心,服務的消費者在進行服務調用的時候先到Zookeeper中查找服務洒放,獲取到服務生產(chǎn)者的詳細信息之后蛉鹿,再去調用服務生產(chǎn)者的內容與數(shù)據(jù)。如下圖所示往湿,在 Dubbo架構中 Zookeeper 就擔任了注冊中心這一角色妖异。
在我自己做過的項目中,主要使用到了 ZooKeeper 作為 Dubbo 的注冊中心(Dubbo 官方推薦使用 ZooKeeper注冊中心)领追。另外在搭建 solr 集群的時候他膳,我使用 ZooKeeper 作為 solr 集群的管理工具。這時绒窑,ZooKeeper 主要提供下面幾個功能:1棕孙、集群管理:容錯、負載均衡。2蟀俊、配置文件的集中管理3钦铺、集群的入口。
我個人覺得在使用 ZooKeeper 的時候肢预,最好是使用 集群版的 ZooKeeper 而不是單機版的矛洞。官網(wǎng)給出的架構圖就描述的是一個集群版的 ZooKeeper 。通常 3 臺服務器就可以構成一個 ZooKeeper 集群了烫映。
為什么最好使用奇數(shù)臺服務器構成 ZooKeeper 集群沼本?
所謂的zookeeper容錯是指,當宕掉幾個zookeeper服務器之后锭沟,剩下的個數(shù)必須大于宕掉的個數(shù)的話整個zookeeper才依然可用抽兆。假如我們的集群中有n臺zookeeper服務器,那么也就是剩下的服務數(shù)必須大于n/2冈钦。先說一下結論,2n和2n-1的容忍度是一樣的李请,都是n-1瞧筛,大家可以先自己仔細想一想,這應該是一個很簡單的數(shù)學問題了导盅。 比如假如我們有3臺较幌,那么最大允許宕掉1臺zookeeper服務器,如果我們有4臺的的時候也同樣只允許宕掉1臺白翻。 假如我們有5臺乍炉,那么最大允許宕掉2臺zookeeper服務器,如果我們有6臺的的時候也同樣只允許宕掉2臺滤馍。
綜上岛琼,何必增加那一個不必要的zookeeper呢?
ZooKeeper 本身就是一個分布式程序(只要半數(shù)以上節(jié)點存活巢株,ZooKeeper 就能正常服務)槐瑞。
為了保證高可用,最好是以集群形態(tài)來部署 ZooKeeper阁苞,這樣只要集群中大部分機器是可用的(能夠容忍一定的機器故障)困檩,那么 ZooKeeper 本身仍然是可用的。
ZooKeeper 將數(shù)據(jù)保存在內存中那槽,這也就保證了 高吞吐量和低延遲(但是內存限制了能夠存儲的容量不太大悼沿,此限制也是保持znode中存儲的數(shù)據(jù)量較小的進一步原因)。
ZooKeeper 是高性能的骚灸。 在“讀”多于“寫”的應用程序中尤其地高性能糟趾,因為“寫”會導致所有的服務器間同步狀態(tài)。(“讀”多于“寫”是協(xié)調服務的典型場景。)
ZooKeeper有臨時節(jié)點的概念拉讯。 當創(chuàng)建臨時節(jié)點的客戶端會話一直保持活動涤浇,瞬時節(jié)點就一直存在。而當會話終結時魔慷,瞬時節(jié)點被刪除只锭。持久節(jié)點是指一旦這個ZNode被創(chuàng)建了,除非主動進行ZNode的移除操作院尔,否則這個ZNode將一直保存在Zookeeper上蜻展。
ZooKeeper 底層其實只提供了兩個功能:①管理(存儲、讀妊凇)用戶程序提交的數(shù)據(jù)纵顾;②為用戶程序提交數(shù)據(jù)節(jié)點監(jiān)聽服務。
下面關于會話(Session)栋盹、 Znode施逾、版本、Watcher例获、ACL概念的總結都在《從Paxos到Zookeeper 》第四章第一節(jié)以及第七章第八節(jié)有提到汉额,感興趣的可以看看!
Session 指的是 ZooKeeper 服務器與客戶端會話榨汤。在 ZooKeeper 中蠕搜,一個客戶端連接是指客戶端和服務器之間的一個 TCP 長連接∈蘸荆客戶端啟動的時候妓灌,首先會與服務器建立一個 TCP 連接,從第一次連接建立開始蜜宪,客戶端會話的生命周期也開始了虫埂。通過這個連接,客戶端能夠通過心跳檢測與服務器保持有效的會話圃验,也能夠向Zookeeper服務器發(fā)送請求并接受響應告丢,同時還能夠通過該連接接收來自服務器的Watch事件通知。?Session的sessionTimeout值用來設置一個客戶端會話的超時時間损谦。當由于服務器壓力太大岖免、網(wǎng)絡故障或是客戶端主動斷開連接等各種原因導致客戶端連接斷開時,只要在sessionTimeout規(guī)定的時間內能夠重新連接上集群中任意一臺服務器照捡,那么之前創(chuàng)建的會話仍然有效颅湘。
在為客戶端創(chuàng)建會話之前,服務端首先會為每個客戶端都分配一個sessionID栗精。由于 sessionID 是 Zookeeper 會話的一個重要標識闯参,許多與會話相關的運行機制都是基于這個 sessionID 的瞻鹏,因此,無論是哪臺服務器為客戶端分配的 sessionID鹿寨,都務必保證全局唯一新博。
在談到分布式的時候,我們通常說的“節(jié)點"是指組成集群的每一臺機器脚草。然而赫悄,在Zookeeper中,“節(jié)點"分為兩類馏慨,第一類同樣是指構成集群的機器埂淮,我們稱之為機器節(jié)點;第二類則是指數(shù)據(jù)模型中的數(shù)據(jù)單元写隶,我們稱之為數(shù)據(jù)節(jié)點一一ZNode倔撞。
Zookeeper將所有數(shù)據(jù)存儲在內存中,數(shù)據(jù)模型是一棵樹(Znode Tree)慕趴,由斜杠(/)的進行分割的路徑痪蝇,就是一個Znode,例如/foo/path1冕房。每個上都會保存自己的數(shù)據(jù)內容躏啰,同時還會保存一系列屬性信息。
**在Zookeeper中毒费,node可以分為持久節(jié)點和臨時節(jié)點兩類丙唧。所謂持久節(jié)點是指一旦這個ZNode被創(chuàng)建了愈魏,除非主動進行ZNode的移除操作觅玻,否則這個ZNode將一直保存在Zookeeper上。而臨時節(jié)點就不一樣了培漏,它的生命周期和客戶端會話綁定溪厘,一旦客戶端會話失效,那么這個客戶端創(chuàng)建的所有臨時節(jié)點都會被移除牌柄。**另外畸悬,ZooKeeper還允許用戶為每個節(jié)點添加一個特殊的屬性:SEQUENTIAL.一旦節(jié)點被標記上這個屬性,那么在這個節(jié)點被創(chuàng)建的時候珊佣,Zookeeper會自動在其節(jié)點名后面追加上一個整型數(shù)字蹋宦,這個整型數(shù)字是一個由父節(jié)點維護的自增數(shù)字。
在前面我們已經(jīng)提到,Zookeeper 的每個 ZNode 上都會存儲數(shù)據(jù),對應于每個ZNode宫屠,Zookeeper 都會為其維護一個叫作?Stat?的數(shù)據(jù)結構消恍,Stat中記錄了這個 ZNode 的三個數(shù)據(jù)版本,分別是version(當前ZNode的版本)邦尊、cversion(當前ZNode子節(jié)點的版本)和 cversion(當前ZNode的ACL版本)兴使。
Watcher(事件監(jiān)聽器)悯搔,是Zookeeper中的一個很重要的特性思灌。Zookeeper允許用戶在指定節(jié)點上注冊一些Watcher俺叭,并且在一些特定事件觸發(fā)的時候,ZooKeeper服務端會將事件通知到感興趣的客戶端上去泰偿,該機制是Zookeeper實現(xiàn)分布式協(xié)調服務的重要特性熄守。
Zookeeper采用ACL(AccessControlLists)策略來進行權限控制,類似于 UNIX 文件系統(tǒng)的權限控制甜奄。Zookeeper 定義了如下5種權限柠横。
其中尤其需要注意的是,CREATE和DELETE這兩種權限都是針對子節(jié)點的權限控制课兄。
順序一致性:?從同一客戶端發(fā)起的事務請求牍氛,最終將會嚴格地按照順序被應用到 ZooKeeper 中去。
原子性:?所有事務請求的處理結果在整個集群中所有機器上的應用情況是一致的烟阐,也就是說搬俊,要么整個集群中所有的機器都成功應用了某一個事務,要么都沒有應用蜒茄。
單一系統(tǒng)映像 :?無論客戶端連到哪一個 ZooKeeper 服務器上唉擂,其看到的服務端數(shù)據(jù)模型都是一致的。
可靠性:?一旦一次更改請求被應用檀葛,更改的結果就會被持久化玩祟,直到被下一次更改覆蓋。
ZooKeeper 允許分布式進程通過共享的層次結構命名空間進行相互協(xié)調屿聋,這與標準文件系統(tǒng)類似空扎。 名稱空間由 ZooKeeper 中的數(shù)據(jù)寄存器組成 - 稱為znode,這些類似于文件和目錄润讥。 與為存儲設計的典型文件系統(tǒng)不同转锈,ZooKeeper數(shù)據(jù)保存在內存中,這意味著ZooKeeper可以實現(xiàn)高吞吐量和低延遲楚殿。
為了保證高可用撮慨,最好是以集群形態(tài)來部署 ZooKeeper,這樣只要集群中大部分機器是可用的(能夠容忍一定的機器故障)脆粥,那么zookeeper本身仍然是可用的砌溺。?客戶端在使用 ZooKeeper 時,需要知道集群機器列表变隔,通過與集群中的某一臺機器建立 TCP 連接來使用服務规伐,客戶端使用這個TCP鏈接來發(fā)送請求、獲取結果弟胀、獲取監(jiān)聽事件以及發(fā)送心跳包楷力。如果這個連接異常斷開了喊式,客戶端可以連接到另外的機器上。
ZooKeeper 官方提供的架構圖:
上圖中每一個Server代表一個安裝Zookeeper服務的服務器萧朝。組成 ZooKeeper 服務的服務器都會在內存中維護當前的服務器狀態(tài)岔留,并且每臺服務器之間都互相保持著通信。集群間通過 Zab 協(xié)議(Zookeeper Atomic Broadcast)來保持數(shù)據(jù)的一致性检柬。
對于來自客戶端的每個更新請求献联,ZooKeeper 都會分配一個全局唯一的遞增編號,這個編號反應了所有事務操作的先后順序何址,應用程序可以使用 ZooKeeper 這個特性來實現(xiàn)更高層次的同步原語里逆。?這個編號也叫做時間戳——zxid(Zookeeper Transaction Id)
ZooKeeper 是高性能的。 在“讀”多于“寫”的應用程序中尤其地高性能用爪,因為“寫”會導致所有的服務器間同步狀態(tài)原押。(“讀”多于“寫”是協(xié)調服務的典型場景。)
最典型集群模式: Master/Slave 模式(主備模式)偎血。在這種模式中诸衔,通常 Master服務器作為主服務器提供寫服務,其他的 Slave 服務器從服務器通過異步復制的方式獲取 Master 服務器最新的數(shù)據(jù)提供讀服務颇玷。
但是笨农,在 ZooKeeper 中沒有選擇傳統(tǒng)的 Master/Slave 概念,而是引入了Leader帖渠、Follower 和 Observer 三種角色谒亦。如下圖所示
ZooKeeper 集群中的所有機器通過一個 Leader 選舉過程來選定一臺稱為 “Leader” 的機器,Leader 既可以為客戶端提供寫服務又能提供讀服務空郊。除了 Leader 外份招,F(xiàn)ollower 和 Observer 都只能提供讀服務。Follower 和 Observer 唯一的區(qū)別在于 Observer 機器不參與 Leader 的選舉過程渣淳,也不參與寫操作的“過半寫成功”策略脾还,因此 Observer 機器可以在不影響寫性能的情況下提升集群的讀性能伴箩。
當 Leader 服務器出現(xiàn)網(wǎng)絡中斷入愧、崩潰退出與重啟等異常情況時,ZAB 協(xié)議就會進人恢復模式并選舉產(chǎn)生新的Leader服務器嗤谚。這個過程大致是這樣的:
Leader election(選舉階段):節(jié)點在一開始都處于選舉階段棺蛛,只要有一個節(jié)點得到超半數(shù)節(jié)點的票數(shù),它就可以當選準 leader巩步。
Discovery(發(fā)現(xiàn)階段):在這個階段旁赊,followers 跟準 leader 進行通信,同步 followers 最近接收的事務提議椅野。
Synchronization(同步階段):同步階段主要是利用 leader 前一階段獲得的最新提議歷史终畅,同步集群中所有的副本籍胯。同步完成之后 準 leader 才會成為真正的 leader。
Broadcast(廣播階段) 到了這個階段离福,Zookeeper 集群才能正式對外提供事務服務杖狼,并且 leader 可以進行消息廣播。同時如果有新的節(jié)點加入妖爷,還需要對新節(jié)點進行同步蝶涩。
六 ZooKeeper &ZAB 協(xié)議&Paxos算法
Paxos 算法應該可以說是 ZooKeeper 的靈魂了。但是絮识,ZooKeeper 并沒有完全采用 Paxos算法 绿聘,而是使用 ZAB 協(xié)議作為其保證數(shù)據(jù)一致性的核心算法。另外次舌,在ZooKeeper的官方文檔中也指出熄攘,ZAB協(xié)議并不像 Paxos 算法那樣,是一種通用的分布式一致性算法彼念,它是一種特別為Zookeeper設計的崩潰可恢復的原子消息廣播算法鲜屏。
ZAB(ZooKeeper Atomic Broadcast 原子廣播) 協(xié)議是為分布式協(xié)調服務 ZooKeeper 專門設計的一種支持崩潰恢復的原子廣播協(xié)議。 在 ZooKeeper 中国拇,主要依賴 ZAB 協(xié)議來實現(xiàn)分布式數(shù)據(jù)一致性洛史,基于該協(xié)議,ZooKeeper 實現(xiàn)了一種主備模式的系統(tǒng)架構來保持集群中各個副本之間的數(shù)據(jù)一致性酱吝。
6.3 ZAB 協(xié)議兩種基本的模式:崩潰恢復和消息廣播
ZAB協(xié)議包括兩種基本的模式也殖,分別是?崩潰恢復和消息廣播。當整個服務框架在啟動過程中务热,或是當 Leader 服務器出現(xiàn)網(wǎng)絡中斷忆嗜、崩潰退出與重啟等異常情況時,ZAB 協(xié)議就會進人恢復模式并選舉產(chǎn)生新的Leader服務器崎岂。當選舉產(chǎn)生了新的 Leader 服務器捆毫,同時集群中已經(jīng)有過半的機器與該Leader服務器完成了狀態(tài)同步之后,ZAB協(xié)議就會退出恢復模式冲甘。其中绩卤,所謂的狀態(tài)同步是指數(shù)據(jù)同步,用來保證集群中存在過半的機器能夠和Leader服務器的數(shù)據(jù)狀態(tài)保持一致江醇。
當集群中已經(jīng)有過半的Follower服務器完成了和Leader服務器的狀態(tài)同步濒憋,那么整個服務框架就可以進人消息廣播模式了。?當一臺同樣遵守ZAB協(xié)議的服務器啟動后加人到集群中時陶夜,如果此時集群中已經(jīng)存在一個Leader服務器在負責進行消息廣播凛驮,那么新加人的服務器就會自覺地進人數(shù)據(jù)恢復模式:找到Leader所在的服務器,并與其進行數(shù)據(jù)同步条辟,然后一起參與到消息廣播流程中去黔夭。正如上文介紹中所說的宏胯,ZooKeeper設計成只允許唯一的一個Leader服務器來進行事務請求的處理。Leader服務器在接收到客戶端的事務請求后本姥,會生成對應的事務提案并發(fā)起一輪廣播協(xié)議胳嘲;而如果集群中的其他機器接收到客戶端的事務請求,那么這些非Leader服務器會首先將這個事務請求轉發(fā)給Leader服務器扣草。
關于?ZAB 協(xié)議&Paxos算法?需要講和理解的東西太多了了牛,說實話,筆主到現(xiàn)在不太清楚這倆兄弟的具體原理和實現(xiàn)過程辰妙。推薦閱讀下面兩篇文章:
關于如何使用 zookeeper 實現(xiàn)分布式鎖鹰祸,可以查看下面這篇文章:
通過閱讀本文密浑,想必大家已從?①ZooKeeper的由來蛙婴。?->?②ZooKeeper 到底是什么 。->?③ ZooKeeper 的一些重要概念(會話(Session)尔破、 Znode街图、版本、Watcher懒构、ACL)->?④ZooKeeper 的特點餐济。?->?⑤ZooKeeper 的設計目標。->?⑥ ZooKeeper 集群角色介紹?(Leader胆剧、Follower 和 Observer 三種角色)->?⑦ZooKeeper &ZAB 協(xié)議&Paxos算法絮姆。?這七點了解了 ZooKeeper 。