深入淺析ZooKeeper的工作原理
本文講述了ZooKeeper的原理,小編覺得挺不錯,分享給大家供大家參考,具體如下:
前言
ZooKeeper 是一個開源的分布式協(xié)調(diào)服務(wù),由雅虎創(chuàng)建,是 Google Chubby 的開源實現(xiàn)。分布式應用程序可以基于 ZooKeeper 實現(xiàn)諸如數(shù)據(jù)發(fā)布/訂閱、負載均衡、命名服務(wù)、分布式協(xié)調(diào)/通知、集群管理、Master 選舉、分布式鎖和分布式隊列等功能。
1、簡介
ZooKeeper 是一個開源的分布式協(xié)調(diào)服務(wù),由雅虎創(chuàng)建,是 Google Chubby 的開源實現(xiàn)。分布式應用程序可以基于 ZooKeeper 實現(xiàn)諸如數(shù)據(jù)發(fā)布/訂閱、負載均衡、命名服務(wù)、分布式協(xié)調(diào)/通知、集群管理、Master 選舉、分布式鎖和分布式隊列等功能。
2、基本概念
本節(jié)將介紹 ZooKeeper 的幾個核心概念。這些概念貫穿于之后對 ZooKeeper 更深入的講解,因此有必要預先了解這些概念。
2.1 集群角色
在 ZooKeeper 中,有三種角色:
Leader
Follower
Observer
一個 ZooKeeper 集群同一時刻只會有一個 Leader,其他都是 Follower 或 Observer。
ZooKeeper 配置很簡單,每個節(jié)點的配置文件(zoo.cfg)都是一樣的,只有 myid 文件不一樣。myid 的值必須是 zoo.cfg中server.{數(shù)值} 的{數(shù)值}部分。
zoo.cfg 文件內(nèi)容示例:
ZooKeeper
在裝有 ZooKeeper 的機器的終端執(zhí)行 zookeeper-server status 可以看當前節(jié)點的 ZooKeeper 是什么角色(Leader or Follower)。
ZooKeeper
如上,node-20-104 是 Leader,node-20-103 是 follower。
ZooKeeper 默認只有 Leader 和 Follower 兩種角色,沒有 Observer 角色。為了使用 Observer 模式,在任何想變成Observer的節(jié)點的配置文件中加入:peerType=observer 并在所有 server 的配置文件中,配置成 observer 模式的 server 的那行配置追加 :observer,例如:
server.1:localhost:2888:3888:observer
ZooKeeper 集群的所有機器通過一個 Leader 選舉過程來選定一臺被稱為『Leader』的機器,Leader服務(wù)器為客戶端提供讀和寫服務(wù)。
Follower 和 Observer 都能提供讀服務(wù),不能提供寫服務(wù)。兩者唯一的區(qū)別在于,Observer 機器不參與 Leader 選舉過程,也不參與寫操作的『過半寫成功』策略,因此 Observer 可以在不影響寫性能的情況下提升集群的讀性能。
2.2 會話(Session)
Session 是指客戶端會話,在講解客戶端會話之前,我們先來了解下客戶端連接。在 ZooKeeper 中,一個客戶端連接是指客戶端和 ZooKeeper 服務(wù)器之間的TCP長連接。
ZooKeeper 對外的服務(wù)端口默認是2181,客戶端啟動時,首先會與服務(wù)器建立一個TCP連接,從第一次連接建立開始,客戶端會話的生命周期也開始了,通過這個連接,客戶端能夠通過心跳檢測和服務(wù)器保持有效的會話,也能夠向 ZooKeeper 服務(wù)器發(fā)送請求并接受響應,同時還能通過該連接接收來自服務(wù)器的 Watch 事件通知。
Session 的 SessionTimeout 值用來設(shè)置一個客戶端會話的超時時間。當由于服務(wù)器壓力太大、網(wǎng)絡(luò)故障或是客戶端主動斷開連接等各種原因?qū)е驴蛻舳诉B接斷開時,只要在 SessionTimeout 規(guī)定的時間內(nèi)能夠重新連接上集群中任意一臺服務(wù)器,那么之前創(chuàng)建的會話仍然有效。
2.3 數(shù)據(jù)節(jié)點(ZNode)
在談到分布式的時候,一般『節(jié)點』指的是組成集群的每一臺機器。而ZooKeeper 中的數(shù)據(jù)節(jié)點是指數(shù)據(jù)模型中的數(shù)據(jù)單元,稱為 ZNode。ZooKeeper 將所有數(shù)據(jù)存儲在內(nèi)存中,數(shù)據(jù)模型是一棵樹(ZNode Tree),由斜杠(/)進行分割的路徑,就是一個ZNode,如 /hbase/master,其中 hbase 和 master 都是 ZNode。每個 ZNode 上都會保存自己的數(shù)據(jù)內(nèi)容,同時會保存一系列屬性信息。
注:
這里的 ZNode 可以理解成既是Unix里的文件,又是Unix里的目錄。因為每個 ZNode 不僅本身可以寫數(shù)據(jù)(相當于Unix里的文件),還可以有下一級文件或目錄(相當于Unix里的目錄)。
在 ZooKeeper 中,ZNode 可以分為持久節(jié)點和臨時節(jié)點兩類。
持久節(jié)點
所謂持久節(jié)點是指一旦這個 ZNode 被創(chuàng)建了,除非主動進行 ZNode 的移除操作,否則這個 ZNode 將一直保存在ZooKeeper 上。
臨時節(jié)點
臨時節(jié)點的生命周期跟客戶端會話綁定,一旦客戶端會話失效,那么這個客戶端創(chuàng)建的所有臨時節(jié)點都會被移除。
另外,ZooKeeper 還允許用戶為每個節(jié)點添加一個特殊的屬性:SEQUENTIAL。一旦節(jié)點被標記上這個屬性,那么在這個節(jié)點被創(chuàng)建的時候,ZooKeeper 就會自動在其節(jié)點后面追加上一個整型數(shù)字,這個整型數(shù)字是一個由父節(jié)點維護的自增數(shù)字。
2.4 版本
ZooKeeper 的每個 ZNode 上都會存儲數(shù)據(jù),對應于每個 ZNode,ZooKeeper 都會為其維護一個叫作 Stat 的數(shù)據(jù)結(jié)構(gòu),Stat 中記錄了這個 ZNode 的三個數(shù)據(jù)版本,分別是 version(當前ZNode的版本)、cversion(當前ZNode子節(jié)點的版本)和 aversion(當前 ZNode 的 ACL 版本)。
2.5 狀態(tài)信息
每個 ZNode 除了存儲數(shù)據(jù)內(nèi)容之外,還存儲了 ZNode 本身的一些狀態(tài)信息。用 get 命令可以同時獲得某個 ZNode 的內(nèi)容和狀態(tài)信息。如下:
ZooKeeper
在 ZooKeeper 中,version 屬性是用來實現(xiàn)樂觀鎖機制中的『寫入校驗』的(保證分布式數(shù)據(jù)原子性操作)。
2.6 事務(wù)操作
在ZooKeeper中,能改變ZooKeeper服務(wù)器狀態(tài)的操作稱為事務(wù)操作。一般包括數(shù)據(jù)節(jié)點創(chuàng)建與刪除、數(shù)據(jù)內(nèi)容更新和客戶端會話創(chuàng)建與失效等操作。對應每一個事務(wù)請求,ZooKeeper 都會為其分配一個全局唯一的事務(wù)ID,用 ZXID 表示,通常是一個64位的數(shù)字。每一個 ZXID 對應一次更新操作,從這些 ZXID 中可以間接地識別出 ZooKeeper 處理這些事務(wù)操作請求的全局順序。
2.7 Watcher
Watcher(事件監(jiān)聽器),是 ZooKeeper 中一個很重要的特性。ZooKeeper允許用戶在指定節(jié)點上注冊一些 Watcher,并且在一些特定事件觸發(fā)的時候,ZooKeeper 服務(wù)端會將事件通知到感興趣的客戶端上去。該機制是 ZooKeeper 實現(xiàn)分布式協(xié)調(diào)服務(wù)的重要特性。
2.8 ACL
ZooKeeper 采用 ACL(Access Control Lists)策略來進行權(quán)限控制。ZooKeeper 定義了如下5種權(quán)限。
CREATE: 創(chuàng)建子節(jié)點的權(quán)限。
READ: 獲取節(jié)點數(shù)據(jù)和子節(jié)點列表的權(quán)限。
WRITE:更新節(jié)點數(shù)據(jù)的權(quán)限。
DELETE: 刪除子節(jié)點的權(quán)限。
ADMIN: 設(shè)置節(jié)點ACL的權(quán)限。
注意:CREATE 和 DELETE 都是針對子節(jié)點的權(quán)限控制。
3. ZooKeeper典型應用場景
ZooKeeper 是一個高可用的分布式數(shù)據(jù)管理與協(xié)調(diào)框架?;趯AB算法的實現(xiàn),該框架能夠很好地保證分布式環(huán)境中數(shù)據(jù)的一致性。也是基于這樣的特性,使得 ZooKeeper 成為了解決分布式一致性問題的利器。
3.1 數(shù)據(jù)發(fā)布與訂閱(配置中心)
數(shù)據(jù)發(fā)布與訂閱,即所謂的配置中心,顧名思義就是發(fā)布者將數(shù)據(jù)發(fā)布到 ZooKeeper 節(jié)點上,供訂閱者進行數(shù)據(jù)訂閱,進而達到動態(tài)獲取數(shù)據(jù)的目的,實現(xiàn)配置信息的集中式管理和動態(tài)更新。
在我們平常的應用系統(tǒng)開發(fā)中,經(jīng)常會碰到這樣的需求:系統(tǒng)中需要使用一些通用的配置信息,例如機器列表信息、數(shù)據(jù)庫配置信息等。這些全局配置信息通常具備以下3個特性。
數(shù)據(jù)量通常比較小。
數(shù)據(jù)內(nèi)容在運行時動態(tài)變化。
集群中各機器共享,配置一致。
對于這樣的全局配置信息就可以發(fā)布到 ZooKeeper上,讓客戶端(集群的機器)去訂閱該消息。
發(fā)布/訂閱系統(tǒng)一般有兩種設(shè)計模式,分別是推(Push)和拉(Pull)模式。
推:服務(wù)端主動將數(shù)據(jù)更新發(fā)送給所有訂閱的客戶端。
拉:客戶端主動發(fā)起請求來獲取最新數(shù)據(jù),通常客戶端都采用定時輪詢拉取的方式。
ZooKeeper 采用的是推拉相結(jié)合的方式。如下:
客戶端想服務(wù)端注冊自己需要關(guān)注的節(jié)點,一旦該節(jié)點的數(shù)據(jù)發(fā)生變更,那么服務(wù)端就會向相應的客戶端發(fā)送Watcher事件通知,客戶端接收到這個消息通知后,需要主動到服務(wù)端獲取最新的數(shù)據(jù)(推拉結(jié)合)。
3.2 命名服務(wù)(Naming Service)
命名服務(wù)也是分布式系統(tǒng)中比較常見的一類場景。在分布式系統(tǒng)中,通過使用命名服務(wù),客戶端應用能夠根據(jù)指定名字來獲取資源或服務(wù)的地址,提供者等信息。被命名的實體通??梢允羌褐械臋C器,提供的服務(wù),遠程對象等等——這些我們都可以統(tǒng)稱他們?yōu)槊郑∟ame)。
其中較為常見的就是一些分布式服務(wù)框架(如RPC、RMI)中的服務(wù)地址列表。通過在ZooKeepr里創(chuàng)建順序節(jié)點,能夠很容易創(chuàng)建一個全局唯一的路徑,這個路徑就可以作為一個名字。
ZooKeeper 的命名服務(wù)即生成全局唯一的ID。
3.3 分布式協(xié)調(diào)/通知
ZooKeeper 中特有 Watcher 注冊與異步通知機制,能夠很好的實現(xiàn)分布式環(huán)境下不同機器,甚至不同系統(tǒng)之間的通知與協(xié)調(diào),從而實現(xiàn)對數(shù)據(jù)變更的實時處理。使用方法通常是不同的客戶端都對ZK上同一個 ZNode 進行注冊,監(jiān)聽 ZNode 的變化(包括ZNode本身內(nèi)容及子節(jié)點的),如果 ZNode 發(fā)生了變化,那么所有訂閱的客戶端都能夠接收到相應的Watcher通知,并做出相應的處理。
ZK的分布式協(xié)調(diào)/通知,是一種通用的分布式系統(tǒng)機器間的通信方式。
3.3.1 心跳檢測
機器間的心跳檢測機制是指在分布式環(huán)境中,不同機器(或進程)之間需要檢測到彼此是否在正常運行,例如A機器需要知道B機器是否正常運行。在傳統(tǒng)的開發(fā)中,我們通常是通過主機直接是否可以相互PING通來判斷,更復雜一點的話,則會通過在機器之間建立長連接,通過TCP連接固有的心跳檢測機制來實現(xiàn)上層機器的心跳檢測,這些都是非常常見的心跳檢測方法。
下面來看看如何使用ZK來實現(xiàn)分布式機器(進程)間的心跳檢測。
基于ZK的臨時節(jié)點的特性,可以讓不同的進程都在ZK的一個指定節(jié)點下創(chuàng)建臨時子節(jié)點,不同的進程直接可以根據(jù)這個臨時子節(jié)點來判斷對應的進程是否存活。通過這種方式,檢測和被檢測系統(tǒng)直接并不需要直接相關(guān)聯(lián),而是通過ZK上的某個節(jié)點進行關(guān)聯(lián),大大減少了系統(tǒng)耦合。
3.3.2 工作進度匯報
在一個常見的任務(wù)分發(fā)系統(tǒng)中,通常任務(wù)被分發(fā)到不同的機器上執(zhí)行后,需要實時地將自己的任務(wù)執(zhí)行進度匯報給分發(fā)系統(tǒng)。這個時候就可以通過ZK來實現(xiàn)。在ZK上選擇一個節(jié)點,每個任務(wù)客戶端都在這個節(jié)點下面創(chuàng)建臨時子節(jié)點,這樣便可以實現(xiàn)兩個功能:
通過判斷臨時節(jié)點是否存在來確定任務(wù)機器是否存活。
各個任務(wù)機器會實時地將自己的任務(wù)執(zhí)行進度寫到這個臨時節(jié)點上去,以便中心系統(tǒng)能夠?qū)崟r地獲取到任務(wù)的執(zhí)行進度。
3.4 Master選舉
Master 選舉可以說是 ZooKeeper 最典型的應用場景了。比如 HDFS 中 Active NameNode 的選舉、YARN 中 Active ResourceManager 的選舉和 HBase 中 Active HMaster 的選舉等。
針對 Master 選舉的需求,通常情況下,我們可以選擇常見的關(guān)系型數(shù)據(jù)庫中的主鍵特性來實現(xiàn):希望成為 Master 的機器都向數(shù)據(jù)庫中插入一條相同主鍵ID的記錄,數(shù)據(jù)庫會幫我們進行主鍵沖突檢查,也就是說,只有一臺機器能插入成功——那么,我們就認為向數(shù)據(jù)庫中成功插入數(shù)據(jù)的客戶端機器成為Master。
依靠關(guān)系型數(shù)據(jù)庫的主鍵特性確實能夠很好地保證在集群中選舉出唯一的一個Master。
但是,如果當前選舉出的 Master 掛了,那么該如何處理?誰來告訴我 Master 掛了呢?顯然,關(guān)系型數(shù)據(jù)庫無法通知我們這個事件。但是,ZooKeeper 可以做到!
利用 ZooKeepr 的強一致性,能夠很好地保證在分布式高并發(fā)情況下節(jié)點的創(chuàng)建一定能夠保證全局唯一性,即 ZooKeeper 將會保證客戶端無法創(chuàng)建一個已經(jīng)存在的 ZNode。
也就是說,如果同時有多個客戶端請求創(chuàng)建同一個臨時節(jié)點,那么最終一定只有一個客戶端請求能夠創(chuàng)建成功。利用這個特性,就能很容易地在分布式環(huán)境中進行 Master 選舉了。
成功創(chuàng)建該節(jié)點的客戶端所在的機器就成為了 Master。同時,其他沒有成功創(chuàng)建該節(jié)點的客戶端,都會在該節(jié)點上注冊一個子節(jié)點變更的 Watcher,用于監(jiān)控當前 Master 機器是否存活,一旦發(fā)現(xiàn)當前的Master掛了,那么其他客戶端將會重新進行 Master 選舉。
這樣就實現(xiàn)了 Master 的動態(tài)選舉。
3.5 分布式鎖
分布式鎖是控制分布式系統(tǒng)之間同步訪問共享資源的一種方式。
分布式鎖又分為排他鎖和共享鎖兩種。
3.5.1 排他鎖
排他鎖(Exclusive Locks,簡稱X鎖),又稱為寫鎖或獨占鎖。
如果事務(wù)T1對數(shù)據(jù)對象O1加上了排他鎖,那么在整個加鎖期間,只允許事務(wù)T1對O1進行讀取和更新操作,其他任何事務(wù)都不能在對這個數(shù)據(jù)對象進行任何類型的操作(不能再對該對象加鎖),直到T1釋放了排他鎖。
可以看出,排他鎖的核心是如何保證當前只有一個事務(wù)獲得鎖,并且鎖被釋放后,所有正在等待獲取鎖的事務(wù)都能夠被通知到。
如何利用 ZooKeeper 實現(xiàn)排他鎖?
定義鎖
ZooKeeper 上的一個 ZNode 可以表示一個鎖。例如 /exclusive_lock/lock節(jié)點就可以被定義為一個鎖。
獲得鎖
如上所說,把ZooKeeper上的一個ZNode看作是一個鎖,獲得鎖就通過創(chuàng)建 ZNode 的方式來實現(xiàn)。所有客戶端都去 /exclusive_lock節(jié)點下創(chuàng)建臨時子節(jié)點 /exclusive_lock/lock。ZooKeeper 會保證在所有客戶端中,最終只有一個客戶端能夠創(chuàng)建成功,那么就可以認為該客戶端獲得了鎖。同時,所有沒有獲取到鎖的客戶端就需要到/exclusive_lock節(jié)點上注冊一個子節(jié)點變更的Watcher監(jiān)聽,以便實時監(jiān)聽到lock節(jié)點的變更情況。
釋放鎖
因為 /exclusive_lock/lock 是一個臨時節(jié)點,因此在以下兩種情況下,都有可能釋放鎖。
當前獲得鎖的客戶端機器發(fā)生宕機或重啟,那么該臨時節(jié)點就會被刪除,釋放鎖。
正常執(zhí)行完業(yè)務(wù)邏輯后,客戶端就會主動將自己創(chuàng)建的臨時節(jié)點刪除,釋放鎖。
無論在什么情況下移除了lock節(jié)點,ZooKeeper 都會通知所有在 /exclusive_lock 節(jié)點上注冊了節(jié)點變更 Watcher 監(jiān)聽的客戶端。這些客戶端在接收到通知后,再次重新發(fā)起分布式鎖獲取,即重復『獲取鎖』過程。
3.5.2 共享鎖
共享鎖(Shared Locks,簡稱S鎖),又稱為讀鎖。如果事務(wù)T1對數(shù)據(jù)對象O1加上了共享鎖,那么T1只能對O1進行讀操作,其他事務(wù)也能同時對O1加共享鎖(不能是排他鎖),直到O1上的所有共享鎖都釋放后O1才能被加排他鎖。
總結(jié):可以多個事務(wù)同時獲得一個對象的共享鎖(同時讀),有共享鎖就不能再加排他鎖(因為排他鎖是寫鎖)
4、ZooKeeper在大型分布式系統(tǒng)中的應用
前面已經(jīng)介紹了 ZooKeeper 的典型應用場景。本節(jié)將以常見的大數(shù)據(jù)產(chǎn)品 Hadoop 和 HBase 為例來介紹 ZooKeeper 在其中的應用,幫助大家更好地理解 ZooKeeper 的分布式應用場景。
4.1 ZooKeeper在Hadoop中的應用
在 Hadoop 中,ZooKeeper 主要用于實現(xiàn) HA(Hive Availability),包括 HDFS的 NamaNode 和 YARN 的 ResourceManager 的 HA。同時,在 YARN 中, ZooKeepr 還用來存儲應用的運行狀態(tài)。
HDFS 的 NamaNode 和 YARN 的 ResourceManager 利用 ZooKeepr 實現(xiàn) HA 的原理是一樣的,所以本節(jié)以YARN為例來介紹。
ZooKeeper
從上圖可以看出,YARN主要由ResourceManager(RM)、NodeManager(NM)、ApplicationMaster(AM)和Container四部分組成。其中最核心的就是ResourceManager。
ResourceManager 負責集群中所有資源的統(tǒng)一管理和分配,同時接收來自各個節(jié)點(NodeManager)的資源匯報信息,并把這些信息按照一定的策略分配給各個應用程序(Application Manager),其內(nèi)部維護了各個應用程序的ApplicationMaster信息、NodeManager信息以及資源使用信息等。
為了實現(xiàn)HA,必須有多個ResourceManager并存(一般就兩個),并且只有一個ResourceManager處于Active狀態(tài),其他的則處于Standby狀態(tài),當Active節(jié)點無法正常工作(如機器宕機或重啟)時,處于Standby的就會通過競爭選舉產(chǎn)生新的Active節(jié)點。
4.2 主備切換
下面我們就來看看YARN是如何實現(xiàn)多個ResourceManager之間的主備切換的。
1. 創(chuàng)建鎖節(jié)點
在 ZooKeeper 上會有一個/yarn-leader-election/appcluster-yarn的鎖節(jié)點,所有的 ResourceManager 在啟動的時候,都會去競爭寫一個Lock子節(jié)點:/yarn-leader-election/appcluster-yarn/ActiveBreadCrumb,該節(jié)點是臨時節(jié)點。
ZooKeepr 能夠為我們保證最終只有一個ResourceManager能夠創(chuàng)建成功。創(chuàng)建成功的那個 ResourceManager 就切換為 Active 狀態(tài),沒有成功的那些 ResourceManager 則切換為 Standby 狀態(tài)。
ZooKeeper
可以看到此時集群中 ResourceManager2 為 Active。
注冊 Watcher 監(jiān)聽
所有 Standby 狀態(tài)的 ResourceManager 都會向 /yarn-leader-election/appcluster-yarn/ActiveBreadCrumb 節(jié)點注冊一個節(jié)點變更的Watcher監(jiān)聽,利用臨時節(jié)點的特性,能夠快速感知到Active狀態(tài)的ResourceManager的運行情況。
主備切換
當Active狀態(tài)的ResourceManager出現(xiàn)諸如宕機或重啟的異常情況時,其在ZooKeeper上連接的客戶端會話就會失效,因此/yarn-leader-election/appcluster-yarn/ActiveBreadCrumb節(jié)點就會被刪除。此時其余各個Standby狀態(tài)的ResourceManager就都會接收到來自ZooKeeper服務(wù)端的Watcher事件通知,然后會重復進行步驟1的操作。
以上就是利用 ZooKeeper 來實現(xiàn) ResourceManager 的主備切換的過程,實現(xiàn)了 ResourceManager 的HA。
HDFS 中 NameNode 的 HA 的實現(xiàn)原理跟 YARN 中 ResourceManager 的 HA 的實現(xiàn)原理相同。其鎖節(jié)點為 /hadoop-ha/mycluster/ActiveBreadCrumb。
4.3 ResourceManager狀態(tài)存儲
在 ResourceManager 中,RMStateStore 能夠存儲一些 RM 的內(nèi)部狀態(tài)信息,包括 Application 以及它們的 Attempts 信息、Delegation Token 及 Version Information 等。需要注意的是,RMStateStore 中的絕大多數(shù)狀態(tài)信息都是不需要持久化存儲的,因為很容易從上下文信息中將其重構(gòu)出來,如資源的使用情況。在存儲的設(shè)計方案中,提供了三種可能的實現(xiàn),分別如下。
基于內(nèi)存實現(xiàn),一般是用于日常開發(fā)測試。
基于文件系統(tǒng)的實現(xiàn),如HDFS。
基于 ZooKeeper 實現(xiàn)。
由于這些狀態(tài)信息的數(shù)據(jù)量都不是很大,因此 Hadoop 官方建議基于 ZooKeeper 來實現(xiàn)狀態(tài)信息的存儲。在 ZooKeepr 上,ResourceManager 的狀態(tài)信息都被存儲在 /rmstore 這個根節(jié)點下面。
ZooKeeper
RMAppRoot 節(jié)點下存儲的是與各個 Application 相關(guān)的信息,RMDTSecretManagerRoot 存儲的是與安全相關(guān)的 Token 等信息。每個 Active 狀態(tài)的 ResourceManager 在初始化階段都會從 ZooKeeper 上讀取到這些狀態(tài)信息,并根據(jù)這些狀態(tài)信息繼續(xù)進行相應的處理。
4.4 小結(jié):
ZooKeepr 在 Hadoop 中的應用主要有:
HDFS 中 NameNode 的 HA 和 YARN 中 ResourceManager 的 HA。
存儲 RMStateStore 狀態(tài)信息
5、ZooKeeper在HBase中的應用
HBase 主要用 ZooKeeper 來實現(xiàn) HMaster 選舉與主備切換、系統(tǒng)容錯、RootRegion 管理、Region狀態(tài)管理和分布式
SplitWAL 任務(wù)管理等。
5.1 HMaster選舉與主備切換
HMaster選舉與主備切換的原理和HDFS中NameNode及YARN中ResourceManager的HA原理相同。
5.2 系統(tǒng)容錯
當 HBase 啟動時,每個 RegionServer 都會到 ZooKeeper 的/hbase/rs節(jié)點下創(chuàng)建一個信息節(jié)點(下文中,我們稱該節(jié)點為”rs狀態(tài)節(jié)點”),例如/hbase/rs/[Hostname],同時,HMaster 會對這個節(jié)點注冊監(jiān)聽。當某個 RegionServer 掛掉的時候,ZooKeeper 會因為在一段時間內(nèi)無法接受其心跳(即 Session 失效),而刪除掉該 RegionServer 服務(wù)器對應的 rs 狀態(tài)節(jié)點。
與此同時,HMaster 則會接收到 ZooKeeper 的 NodeDelete 通知,從而感知到某個節(jié)點斷開,并立即開始容錯工作。
HBase 為什么不直接讓 HMaster 來負責 RegionServer 的監(jiān)控呢?如果 HMaster 直接通過心跳機制等來管理RegionServer的狀態(tài),隨著集群越來越大,HMaster 的管理負擔會越來越重,另外它自身也有掛掉的可能,因此數(shù)據(jù)還需要持久化。在這種情況下,ZooKeeper 就成了理想的選擇。
5.3 RootRegion管理
對應 HBase 集群來說,數(shù)據(jù)存儲的位置信息是記錄在元數(shù)據(jù) region,也就是 RootRegion 上的。每次客戶端發(fā)起新的請求,需要知道數(shù)據(jù)的位置,就會去查詢 RootRegion,而 RootRegion 自身位置則是記錄在 ZooKeeper 上的(默認情況下,是記錄在 ZooKeeper 的/hbase/meta-region-server節(jié)點中)。
當 RootRegion 發(fā)生變化,比如 Region 的手工移動、重新負載均衡或 RootRegion 所在服務(wù)器發(fā)生了故障等是,就能夠通過 ZooKeeper 來感知到這一變化并做出一系列相應的容災措施,從而保證客戶端總是能夠拿到正確的 RootRegion 信息。
5.4 Region管理
HBase 里的 Region 會經(jīng)常發(fā)生變更,這些變更的原因來自于系統(tǒng)故障、負載均衡、配置修改、Region 分裂與合并等。一旦 Region 發(fā)生移動,它就會經(jīng)歷下線(offline)和重新上線(online)的過程。
在下線期間數(shù)據(jù)是不能被訪問的,并且 Region 的這個狀態(tài)變化必須讓全局知曉,否則可能會出現(xiàn)事務(wù)性的異常。
對于大的 HBase 集群來說,Region 的數(shù)量可能會多達十萬級別,甚至更多,這樣規(guī)模的 Region 狀態(tài)管理交給 ZooKeeper 來做也是一個很好的選擇。
5.5 分布式SplitWAL任務(wù)管理
當某臺 RegionServer 服務(wù)器掛掉時,由于總有一部分新寫入的數(shù)據(jù)還沒有持久化到 HFile 中,因此在遷移該 RegionServer 的服務(wù)時,一個重要的工作就是從 WAL 中恢復這部分還在內(nèi)存中的數(shù)據(jù),而這部分工作最關(guān)鍵的一步就是 SplitWAL,即 HMaster 需要遍歷該 RegionServer 服務(wù)器的 WAL,并按 Region 切分成小塊移動到新的地址下,并進行日志的回放(replay)。
由于單個 RegionServer 的日志量相對龐大(可能有上千個 Region,上GB的日志),而用戶又往往希望系統(tǒng)能夠快速完成日志的恢復工作。因此一個可行的方案是將這個處理WAL的任務(wù)分給多臺 RegionServer 服務(wù)器來共同處理,而這就又需要一個持久化組件來輔助 HMaster 完成任務(wù)的分配。
當前的做法是, HMaster 會在 ZooKeeper 上創(chuàng)建一個 SplitWAL 節(jié)點(默認情況下,是/hbase/SplitWAL節(jié)點),將“哪個 RegionServer 處理哪個 Region”這樣的信息以列表的形式存放到該節(jié)點上,然后由各個 RegionServer 服務(wù)器自行到該節(jié)點上去領(lǐng)取任務(wù)并在任務(wù)執(zhí)行成功或失敗后再更新該節(jié)點的信息,以通知 HMaster 繼續(xù)進行后面的步驟。 ZooKeeper 在這里擔負起了分布式集群中相互通知和信息持久化的角色。
5.6 小結(jié):
以上就是一些 HBase 中依賴 ZooKeeper 完成分布式協(xié)調(diào)功能的典型場景。但事實上,HBase 對 ZooKeeper 的依賴還不止這些,比如 HMaster 還依賴 ZooKeeper 來完成 Table 的 enable/disable 狀態(tài)記錄,以及 HBase 中幾乎所有的元數(shù)據(jù)存儲都是放在 ZooKeeper 上的。
由于 ZooKeeper 出色的分布式協(xié)調(diào)能力及良好的通知機制,HBase在各版本的演進過程中越來越多地增加了 ZooKeeper 的應用場景,從趨勢上來看兩者的交集越來越多。HBase 中所有對 ZooKeeper 的操作都封裝在了 org.apache.hadoop.hbase.zookeeper 這個包中,感興趣的同學可以自行研究。
以上所述是小編給大家介紹的Spring Boot 模塊組成,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的!
相關(guān)文章
Elasticsearch寫入瓶頸導致skywalking大盤空白
這篇文章主要為大家介紹了Elasticsearch寫入瓶頸導致skywalking大盤空白的解決方案,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步2022-02-02java調(diào)用ffmpeg實現(xiàn)轉(zhuǎn)換視頻
這篇文章主要為大家詳細介紹了java調(diào)用ffmpeg實現(xiàn)轉(zhuǎn)換視頻功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-12-12Java?for循環(huán)標簽跳轉(zhuǎn)到指定位置的示例詳解
這篇文章主要介紹了Java?for循環(huán)標簽跳轉(zhuǎn)到指定位置,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-05-05Java中的StackOverflowError錯誤問題及解決方法
這篇文章主要介紹了Java中的StackOverflowError錯誤,在本文中,我們仔細研究了StackOverflower錯誤,包括Java代碼如何導致它,以及我們?nèi)绾卧\斷和修復它,需要的朋友可以參考下2022-07-07教你從頭開始用JAVA創(chuàng)建一個自己的簡單API并實現(xiàn)第三方調(diào)用
在日常開發(fā)的時候,經(jīng)常會遇到需要調(diào)用別人的接口的場景,下面這篇文章主要給大家介紹了關(guān)于如何從頭開始用JAVA創(chuàng)建一個自己的簡單API并實現(xiàn)第三方調(diào)用的相關(guān)資料,需要的朋友可以參考下2023-12-12