ZooKeeper 原理及其在 Hadoop 和 HBase 中的應用

       ZooKeeper是一個開源的分佈式協調服務,由雅虎建立,是Google Chubby的開源實現。分佈式應用程序能夠基於ZooKeeper實現諸如數據發佈/訂閱、負載均衡、命名服務、分佈式協調/通知、集羣管理、Master選舉、分佈式鎖和分佈式隊列等功能。node

簡介

ZooKeeper是一個開源的分佈式協調服務,由雅虎建立,是Google Chubby的開源實現。分佈式應用程序能夠基於ZooKeeper實現諸如數據發佈/訂閱、負載均衡、命名服務、分佈式協調/通知、集羣管理、Master選舉、分佈式鎖和分佈式隊列等功能。算法

基本概念

本節將介紹ZooKeeper的幾個核心概念。這些概念貫穿於以後對ZooKeeper更深刻的講解,所以有必要預先了解這些概念。數據庫

集羣角色

在ZooKeeper中,有三種角色:apache

  • Leader
  • Follower
  • Observer

一個ZooKeeper集羣同一時刻只會有一個Leader,其餘都是Follower或Observer。設計模式

ZooKeeper配置很簡單,每一個節點的配置文件(zoo.cfg)都是同樣的,只有myid文件不同。myid的值必須是zoo.cfg中server.{數值}的{數值}部分。安全

zoo.cfg文件內容示例:服務器

maxClientCnxns=0 # The number of milliseconds of each tick tickTime=2000 # The number of ticks that the initial # synchronization phase can take initLimit=10 # The number of ticks that can pass between # sending a request and getting an acknowledgement syncLimit=5 # the directory where the snapshot is stored. dataDir=/var/lib/zookeeper/data # the port at which the clients will connect clientPort=2181 # the directory where the transaction logs are stored. dataLogDir=/var/lib/zookeeper/logs server.1=192.168.20.101:2888:3888 server.2=192.168.20.102:2888:3888 server.3=192.168.20.103:2888:3888 server.4=192.168.20.104:2888:3888 server.5=192.168.20.105:2888:3888 minSessionTimeout=4000 maxSessionTimeout=100000網絡

1數據結構

2架構

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

maxClientCnxns=0

# The number of milliseconds of each tick

tickTime=2000

# The number of ticks that the initial

# synchronization phase can take

initLimit=10

# The number of ticks that can pass between

# sending a request and getting an acknowledgement

syncLimit=5

# the directory where the snapshot is stored.

dataDir=/var/lib/zookeeper/data

# the port at which the clients will connect

clientPort=2181

# the directory where the transaction logs are stored.

dataLogDir=/var/lib/zookeeper/logs

server.1=192.168.20.101:2888:3888

server.2=192.168.20.102:2888:3888

server.3=192.168.20.103:2888:3888

server.4=192.168.20.104:2888:3888

server.5=192.168.20.105:2888:3888

minSessionTimeout=4000

maxSessionTimeout=100000

在裝有ZooKeeper的機器的終端執行 zookeeper-server status 能夠看當前節點的ZooKeeper是什麼角色(Leader or Follower)。

[root@node-20-103 ~]# zookeeper-server status JMX enabled by default Using config: /etc/zookeeper/conf/zoo.cfg Mode: follower

1

2

3

4

[root@node-20-103 ~]# zookeeper-server status

JMX enabled by default

Using config: /etc/zookeeper/conf/zoo.cfg

Mode: follower

 

[root@node-20-104 ~]# zookeeper-server status JMX enabled by default Using config: /etc/zookeeper/conf/zoo.cfg Mode: leader

1

2

3

4

[root@node-20-104 ~]# zookeeper-server status

JMX enabled by default

Using config: /etc/zookeeper/conf/zoo.cfg

Mode: leader

如上,node-20-104是Leader,node-20-103是follower。

ZooKeeper默認只有Leader和Follower兩種角色,沒有Observer角色。

爲了使用Observer模式,在任何想變成Observer的節點的配置文件中加入:peerType=observer
並在全部server的配置文件中,配置成observer模式的server的那行配置追加:observer,例如:
server.1:localhost:2888:3888:observer

ZooKeeper集羣的全部機器經過一個Leader選舉過程來選定一臺被稱爲『Leader』的機器,Leader服務器爲客戶端提供服務。

Follower和Observer都提供服務,不能提供服務。二者惟一的區別在於,Observer機器不參與Leader選舉過程,也不參與寫操做的『過半寫成功』策略,所以Observer能夠在不影響寫性能的狀況下提高集羣的讀性能

會話(Session)

Session是指客戶端會話,在講解客戶端會話以前,咱們先來了解下客戶端鏈接。在ZooKeeper中,一個客戶端鏈接是指客戶端和ZooKeeper服務器之間的TCP長鏈接。ZooKeeper對外的服務端口默認是2181,客戶端啓動時,首先會與服務器創建一個TCP鏈接,從第一次鏈接創建開始,客戶端會話的生命週期也開始了,經過這個鏈接,客戶端可以經過心跳檢測和服務器保持有效的會話,也可以向ZooKeeper服務器發送請求接受響應,同時還能經過該鏈接接收來自服務器的Watch事件通知。Session的SessionTimeout值用來設置一個客戶端會話的超時時間。當因爲服務器壓力太大、網絡故障或是客戶端主動斷開鏈接等各類緣由致使客戶端鏈接斷開時,只要在SessionTimeout規定的時間內可以從新鏈接上集羣中任意一臺服務器,那麼以前建立的會話仍然有效

數據節點(ZNode)

在談到分佈式的時候,通常『節點』指的是組成集羣的每一臺機器。而ZooKeeper中的數據節點是指數據模型中的數據單元,稱爲ZNode。ZooKeeper將全部數據存儲在內存中,數據模型是一棵樹(ZNode Tree),由斜槓(/)進行分割的路徑,就是一個ZNode,如/hbase/master,其中hbase和master都是ZNode。每一個ZNode上都會保存本身的數據內容,同時會保存一系列屬性信息

注:
這裏的ZNode能夠理解成既是Unix裏的文件又是Unix裏的目錄。由於每一個ZNode不只自己能夠寫數據(至關於Unix裏的文件),還能夠有下一級文件或目錄(至關於Unix裏的目錄)。

在ZooKeeper中,ZNode能夠分爲持久節點臨時節點兩類。

持久節點

所謂持久節點是指一旦這個ZNode被建立了,除非主動進行ZNode的移除操做,不然這個ZNode將一直保存在ZooKeeper上。

臨時節點

臨時節點的生命週期跟客戶端會話綁定,一旦客戶端會話失效,那麼這個客戶端建立的全部臨時節點都會被移除。

另外,ZooKeeper還容許用戶爲每一個節點添加一個特殊的屬性:SEQUENTIAL。一旦節點被標記上這個屬性,那麼在這個節點被建立的時候,ZooKeeper就會自動在其節點後面追加上一個整型數字,這個整型數字是一個由父節點維護的自增數字。

版本

ZooKeeper的每一個ZNode上都會存儲數據,對應於每一個ZNode,ZooKeeper都會爲其維護一個叫做Stat的數據結構,Stat中記錄了這個ZNode的三個數據版本,分別是version(當前ZNode的版本)、cversion(當前ZNode子節點的版本)和aversion(當前ZNode的ACL版本)。

狀態信息

每一個ZNode除了存儲數據內容以外,還存儲了ZNode自己的一些狀態信息。用 get 命令能夠同時得到某個ZNode的內容和狀態信息。以下:

[zk: localhost:2181(CONNECTED) 23] get /yarn-leader-election/appcluster-yarn/ActiveBreadCrumb appcluster-yarnrm1 cZxid = 0x1b00133dc0 //Created ZXID,表示該ZNode被建立時的事務ID ctime = Tue Jan 03 15:44:42 CST 2017 //Created Time,表示該ZNode被建立的時間 mZxid = 0x1d00000063 //Modified ZXID,表示該ZNode最後一次被更新時的事務ID mtime = Fri Jan 06 08:44:25 CST 2017 //Modified Time,表示該節點最後一次被更新的時間 pZxid = 0x1b00133dc0 //表示該節點的子節點列表最後一次被修改時的事務ID。注意,只有子節點列表變動了纔會變動pZxid,子節點內容變動不會影響pZxid。 cversion = 0 //子節點的版本號 dataVersion = 11 //數據節點的版本號 aclVersion = 0 //ACL版本號 ephemeralOwner = 0x0 //建立該節點的會話的seddionID。若是該節點是持久節點,那麼這個屬性值爲0。 dataLength = 22 //數據內容的長度 numChildren = 0 //子節點的個數

1

2

3

4

5

6

7

8

9

10

11

12

13

[zk: localhost:2181(CONNECTED) 23] get /yarn-leader-election/appcluster-yarn/ActiveBreadCrumb

appcluster-yarnrm1

cZxid = 0x1b00133dc0    //Created ZXID,表示該ZNode被建立時的事務ID

ctime = Tue Jan 03 15:44:42 CST 2017    //Created Time,表示該ZNode被建立的時間

mZxid = 0x1d00000063    //Modified ZXID,表示該ZNode最後一次被更新時的事務ID

mtime = Fri Jan 06 08:44:25 CST 2017    //Modified Time,表示該節點最後一次被更新的時間

pZxid = 0x1b00133dc0    //表示該節點的子節點列表最後一次被修改時的事務ID。注意,只有子節點列表變動了纔會變動pZxid,子節點內容變動不會影響pZxid。

cversion = 0    //子節點的版本號

dataVersion = 11    //數據節點的版本號

aclVersion = 0    //ACL版本號

ephemeralOwner = 0x0    //建立該節點的會話的seddionID。若是該節點是持久節點,那麼這個屬性值爲0。

dataLength = 22    //數據內容的長度

numChildren = 0    //子節點的個數

在ZooKeeper中,version屬性是用來實現樂觀鎖機制中的『寫入校驗』的(保證分佈式數據原子性操做)。

事務操做

在ZooKeeper中,能改變ZooKeeper服務器狀態的操做稱爲事務操做。通常包括數據節點建立與刪除、數據內容更新和客戶端會話建立與失效等操做。對應每個事務請求,ZooKeeper都會爲其分配一個全局惟一的事務ID,用ZXID表示,一般是一個64位的數字。每個ZXID對應一次更新操做,從這些ZXID中能夠間接地識別出ZooKeeper處理這些事務操做請求的全局順序。

Watcher

Watcher(事件監聽器),是ZooKeeper中一個很重要的特性。ZooKeeper容許用戶在指定節點上註冊一些Watcher,而且在一些特定事件觸發的時候,ZooKeeper服務端會將事件通知到感興趣的客戶端上去。該機制是ZooKeeper實現分佈式協調服務的重要特性。

ACL

ZooKeeper採用ACL(Access Control Lists)策略來進行權限控制。ZooKeeper定義了以下5種權限。

  • CREATE: 建立子節點的權限。
  • READ: 獲取節點數據和子節點列表的權限。
  • WRITE:更新節點數據的權限。
  • DELETE: 刪除子節點的權限。
  • ADMIN: 設置節點ACL的權限。

注意:CREATE 和 DELETE 都是針對子節點的權限控制。

ZooKeeper典型應用場景

ZooKeeper是一個高可用的分佈式數據管理與協調框架。基於對ZAB算法的實現,該框架可以很好地保證分佈式環境中數據的一致性。也是基於這樣的特性,使得ZooKeeper成爲了解決分佈式一致性問題的利器。

數據發佈與訂閱(配置中心)

數據發佈與訂閱,即所謂的配置中心,顧名思義就是發佈者將數據發佈到ZooKeeper節點上,供訂閱者進行數據訂閱,進而達到動態獲取數據的目的,實現配置信息的集中式管理動態更新

在咱們日常的應用系統開發中,常常會碰到這樣的需求:系統中須要使用一些通用的配置信息,例如機器列表信息數據庫配置信息等。這些全局配置信息一般具有如下3個特性。

  • 數據量一般比較小。
  • 數據內容在運行時動態變化
  • 集羣中各機器共享,配置一致

對於這樣的全局配置信息就能夠發佈到ZooKeeper上,讓客戶端(集羣的機器)去訂閱該消息。

發佈/訂閱系統通常有兩種設計模式,分別是推(Push)拉(Pull)模式。

  • 推:服務端主動將數據更新發送給全部訂閱的客戶端。
  • 拉:客戶端主動發起請求來獲取最新數據,一般客戶端都採用定時輪詢拉取的方式。

ZooKeeper採用的是推拉相結合的方式。以下:

客戶端想服務端註冊本身須要關注的節點,一旦該節點的數據發生變動,那麼服務端就會向相應的客戶端發送Watcher事件通知,客戶端接收到這個消息通知後,須要主動到服務端獲取最新的數據(推拉結合)。

命名服務(Naming Service)

命名服務也是分佈式系統中比較常見的一類場景。在分佈式系統中,經過使用命名服務,客戶端應用可以根據指定名字來獲取資源或服務的地址,提供者等信息。被命名的實體一般能夠是集羣中的機器,提供的服務,遠程對象等等——這些咱們均可以統稱他們爲名字(Name)。其中較爲常見的就是一些分佈式服務框架(如RPC、RMI)中的服務地址列表。經過在ZooKeepr裏建立順序節點,可以很容易建立一個全局惟一的路徑,這個路徑就能夠做爲一個名字

ZooKeeper的命名服務即生成全局惟一的ID

分佈式協調/通知

ZooKeeper中特有Watcher註冊異步通知機制,可以很好的實現分佈式環境下不一樣機器,甚至不一樣系統之間的通知與協調,從而實現對數據變動的實時處理。使用方法一般是不一樣的客戶端都對ZK上同一個ZNode進行註冊,監聽ZNode的變化(包括ZNode自己內容及子節點的),若是ZNode發生了變化,那麼全部訂閱的客戶端都可以接收到相應的Watcher通知,並作出相應的處理。

ZK的分佈式協調/通知,是一種通用的分佈式系統機器間的通訊方式

心跳檢測

機器間的心跳檢測機制是指在分佈式環境中,不一樣機器(或進程)之間須要檢測到彼此是否在正常運行,例如A機器須要知道B機器是否正常運行。在傳統的開發中,咱們一般是經過主機直接是否能夠相互PING通來判斷,更復雜一點的話,則會經過在機器之間創建長鏈接,經過TCP鏈接固有的心跳檢測機制來實現上層機器的心跳檢測,這些都是很是常見的心跳檢測方法。

下面來看看如何使用ZK來實現分佈式機器(進程)間的心跳檢測。

基於ZK的臨時節點的特性,可讓不一樣的進程都在ZK的一個指定節點下建立臨時子節點,不一樣的進程直接能夠根據這個臨時子節點來判斷對應的進程是否存活。經過這種方式,檢測和被檢測系統直接並不須要直接相關聯,而是經過ZK上的某個節點進行關聯,大大減小了系統耦合

工做進度彙報

在一個常見的任務分發系統中,一般任務被分發到不一樣的機器上執行後,須要實時地將本身的任務執行進度彙報給分發系統。這個時候就能夠經過ZK來實現。在ZK上選擇一個節點,每一個任務客戶端都在這個節點下面建立臨時子節點,這樣即可以實現兩個功能:

  • 經過判斷臨時節點是否存在來肯定任務機器是否存活
  • 各個任務機器會實時地將本身的任務執行進度寫到這個臨時節點上去,以便中心繫統可以實時地獲取到任務的執行進度

Master選舉

Master選舉能夠說是ZooKeeper最典型的應用場景了。好比HDFS中Active NameNode的選舉、YARN中Active ResourceManager的選舉和HBase中Active HMaster的選舉等。

針對Master選舉的需求,一般狀況下,咱們能夠選擇常見的關係型數據庫中的主鍵特性來實現:但願成爲Master的機器都向數據庫中插入一條相同主鍵ID的記錄,數據庫會幫咱們進行主鍵衝突檢查,也就是說,只有一臺機器能插入成功——那麼,咱們就認爲向數據庫中成功插入數據的客戶端機器成爲Master

依靠關係型數據庫的主鍵特性確實可以很好地保證在集羣中選舉出惟一的一個Master。可是,若是當前選舉出的Master掛了,那麼該如何處理?誰來告訴我Master掛了呢?顯然,關係型數據庫沒法通知咱們這個事件。可是,ZooKeeper能夠作到!

利用ZooKeepr的強一致性,可以很好地保證在分佈式高併發狀況下節點的建立必定可以保證全局惟一性,即ZooKeeper將會保證客戶端沒法建立一個已經存在的ZNode。也就是說,若是同時有多個客戶端請求建立同一個臨時節點,那麼最終必定只有一個客戶端請求可以建立成功。利用這個特性,就能很容易地在分佈式環境中進行Master選舉了。

成功建立該節點的客戶端所在的機器就成爲了Master。同時,其餘沒有成功建立該節點的客戶端,都會在該節點上註冊一個子節點變動的Watcher,用於監控當前Master機器是否存活,一旦發現當前的Master掛了,那麼其餘客戶端將會從新進行Master選舉

這樣就實現了Master的動態選舉

分佈式鎖

分佈式鎖是控制分佈式系統之間同步訪問共享資源的一種方式。

分佈式鎖又分爲排他鎖共享鎖兩種。

排他鎖

排他鎖(Exclusive Locks,簡稱X鎖),又稱爲寫鎖獨佔鎖

若是事務T1對數據對象O1加上了排他鎖,那麼在整個加鎖期間,只容許事務T1對O1進行讀取和更新操做,其餘任何事務都不能在對這個數據對象進行任何類型的操做(不能再對該對象加鎖),直到T1釋放了排他鎖。

能夠看出,排他鎖的核心是如何保證當前只有一個事務得到鎖,而且鎖被釋放後,全部正在等待獲取鎖的事務都可以被通知到

如何利用ZooKeeper實現排他鎖?

定義鎖

ZooKeeper上的一個ZNode能夠表示一個鎖。例如/exclusive_lock/lock節點就能夠被定義爲一個鎖。

得到鎖

如上所說,把ZooKeeper上的一個ZNode看做是一個鎖,得到鎖就經過建立ZNode的方式來實現。全部客戶端都去/exclusive_lock節點下建立臨時子節點/exclusive_lock/lock。ZooKeeper會保證在全部客戶端中,最終只有一個客戶端可以建立成功,那麼就能夠認爲該客戶端得到了鎖。同時,全部沒有獲取到鎖的客戶端就須要到/exclusive_lock節點上註冊一個子節點變動的Watcher監聽,以便實時監聽到lock節點的變動狀況。

釋放鎖

由於/exclusive_lock/lock是一個臨時節點,所以在如下兩種狀況下,都有可能釋放鎖。

  • 當前得到鎖的客戶端機器發生宕機重啓,那麼該臨時節點就會被刪除,釋放鎖
  • 正常執行完業務邏輯後,客戶端就會主動將本身建立的臨時節點刪除,釋放鎖

不管在什麼狀況下移除了lock節點,ZooKeeper都會通知全部在/exclusive_lock節點上註冊了節點變動Watcher監聽的客戶端。這些客戶端在接收到通知後,再次從新發起分佈式鎖獲取,即重複『獲取鎖』過程。

共享鎖

共享鎖(Shared Locks,簡稱S鎖),又稱爲讀鎖。若是事務T1對數據對象O1加上了共享鎖,那麼T1只能對O1進行讀操做,其餘事務也能同時對O1加共享鎖(不能是排他鎖),直到O1上的全部共享鎖都釋放後O1才能被加排他鎖。

總結:能夠多個事務同時得到一個對象的共享鎖(同時讀),有共享鎖就不能再加排他鎖(由於排他鎖是寫鎖)

ZooKeeper在大型分佈式系統中的應用

前面已經介紹了ZooKeeper的典型應用場景。本節將以常見的大數據產品Hadoop和HBase爲例來介紹ZooKeeper在其中的應用,幫助你們更好地理解ZooKeeper的分佈式應用場景。

ZooKeeper在Hadoop中的應用

在Hadoop中,ZooKeeper主要用於實現HA(Hive Availability),包括HDFS的NamaNode和YARN的ResourceManager的HA。同時,在YARN中,ZooKeepr還用來存儲應用的運行狀態。HDFS的NamaNode和YARN的ResourceManager利用ZooKeepr實現HA的原理是同樣的,因此本節以YARN爲例來介紹。

YARN架構體系

從上圖能夠看出,YARN主要由ResourceManager(RM)、NodeManager(NM)、ApplicationMaster(AM)和Container四部分組成。其中最核心的就是ResourceManager

ResourceManager負責集羣中全部資源的統一管理和分配,同時接收來自各個節點(NodeManager)的資源彙報信息,並把這些信息按照必定的策略分配給各個應用程序(Application Manager),其內部維護了各個應用程序的ApplicationMaster信息、NodeManager信息以及資源使用信息等。

爲了實現HA,必須有多個ResourceManager並存(通常就兩個),而且只有一個ResourceManager處於Active狀態,其餘的則處於Standby狀態,當Active節點沒法正常工做(如機器宕機或重啓)時,處於Standby的就會經過競爭選舉產生新的Active節點

主備切換

下面咱們就來看看YARN是如何實現多個ResourceManager之間的主備切換的。

  1. 建立鎖節點
    在ZooKeeper上會有一個/yarn-leader-election/appcluster-yarn的鎖節點,全部的ResourceManager在啓動的時候,都會去競爭寫一個Lock子節點:/yarn-leader-election/appcluster-yarn/ActiveBreadCrumb,該節點是臨時節點。ZooKeepr可以爲咱們保證最終只有一個ResourceManager可以建立成功建立成功的那個ResourceManager就切換爲Active狀態沒有成功的那些ResourceManager則切換爲Standby狀態

    [zk: localhost:2181(CONNECTED) 16] get /yarn-leader-election/appcluster-yarn/ActiveBreadCrumb appcluster-yarnrm2 cZxid = 0x1b00133dc0 ctime = Tue Jan 03 15:44:42 CST 2017 mZxid = 0x1f00000540 mtime = Sat Jan 07 00:50:20 CST 2017 pZxid = 0x1b00133dc0 cversion = 0 dataVersion = 28 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 22 numChildren = 0

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    [zk: localhost:2181(CONNECTED) 16] get /yarn-leader-election/appcluster-yarn/ActiveBreadCrumb

    appcluster-yarnrm2

    cZxid = 0x1b00133dc0

    ctime = Tue Jan 03 15:44:42 CST 2017

    mZxid = 0x1f00000540

    mtime = Sat Jan 07 00:50:20 CST 2017

    pZxid = 0x1b00133dc0

    cversion = 0

    dataVersion = 28

    aclVersion = 0

    ephemeralOwner = 0x0

    dataLength = 22

    numChildren = 0

能夠看到此時集羣中ResourceManager2爲Active。

  1. 註冊Watcher監聽
    全部Standby狀態的ResourceManager都會向/yarn-leader-election/appcluster-yarn/ActiveBreadCrumb節點註冊一個節點變動的Watcher監聽,利用臨時節點的特性,可以快速感知到Active狀態的ResourceManager的運行狀況。
  2. 主備切換
    當Active狀態的ResourceManager出現諸如宕機或重啓的異常狀況時,其在ZooKeeper上鍊接的客戶端會話就會失效,所以/yarn-leader-election/appcluster-yarn/ActiveBreadCrumb節點就會被刪除。此時其他各個Standby狀態的ResourceManager就都會接收到來自ZooKeeper服務端的Watcher事件通知,而後會重複進行步驟1的操做

以上就是利用ZooKeeper來實現ResourceManager的主備切換的過程,實現了ResourceManager的HA。

HDFS中NameNode的HA的實現原理跟YARN中ResourceManager的HA的實現原理相同。其鎖節點爲/hadoop-ha/mycluster/ActiveBreadCrumb

ResourceManager狀態存儲

在 ResourceManager 中,RMStateStore 可以存儲一些 RM 的內部狀態信息,包括 Application 以及它們的 Attempts 信息、Delegation Token 及 Version Information 等。須要注意的是,RMStateStore 中的絕大多數狀態信息都是不須要持久化存儲的,由於很容易從上下文信息中將其重構出來,如資源的使用狀況。在存儲的設計方案中,提供了三種可能的實現,分別以下。

  • 基於內存實現,通常是用於平常開發測試。
  • 基於文件系統的實現,如HDFS。
  • 基於ZooKeeper實現。

因爲這些狀態信息的數據量都不是很大,所以Hadoop官方建議基於ZooKeeper來實現狀態信息的存儲。在ZooKeepr上,ResourceManager 的狀態信息都被存儲在/rmstore這個根節點下面。

[zk: localhost:2181(CONNECTED) 28] ls /rmstore/ZKRMStateRoot [RMAppRoot, AMRMTokenSecretManagerRoot, EpochNode, RMDTSecretManagerRoot, RMVersionNode]

1

2

[zk: localhost:2181(CONNECTED) 28] ls /rmstore/ZKRMStateRoot

[RMAppRoot, AMRMTokenSecretManagerRoot, EpochNode, RMDTSecretManagerRoot, RMVersionNode]

RMAppRoot 節點下存儲的是與各個 Application 相關的信息,RMDTSecretManagerRoot 存儲的是與安全相關的 Token 等信息。每一個 Active 狀態的 ResourceManager 在初始化階段都會從 ZooKeeper 上讀取到這些狀態信息,並根據這些狀態信息繼續進行相應的處理。

小結:

ZooKeepr在Hadoop中的應用主要有:

  1. HDFS中NameNode的HA和YARN中ResourceManager的HA。
  2. 存儲RMStateStore狀態信息

ZooKeeper在HBase中的應用

HBase主要用ZooKeeper來實現HMaster選舉與主備切換、系統容錯、RootRegion管理、Region狀態管理和分佈式SplitWAL任務管理等。

HMaster選舉與主備切換

HMaster選舉與主備切換的原理和HDFS中NameNode及YARN中ResourceManager的HA原理相同。

系統容錯

當HBase啓動時,每一個RegionServer都會到ZooKeeper的/hbase/rs節點下建立一個信息節點(下文中,咱們稱該節點爲」rs狀態節點」),例如/hbase/rs/[Hostname],同時,HMaster會對這個節點註冊監聽。當某個 RegionServer 掛掉的時候,ZooKeeper會由於在一段時間內沒法接受其心跳(即 Session 失效),而刪除掉該 RegionServer 服務器對應的 rs 狀態節點。與此同時,HMaster 則會接收到 ZooKeeper 的 NodeDelete 通知,從而感知到某個節點斷開,並當即開始容錯工做。

HBase爲何不直接讓HMaster來負責RegionServer的監控呢?若是HMaster直接經過心跳機制等來管理RegionServer的狀態,隨着集羣愈來愈大,HMaster的管理負擔會愈來愈重,另外它自身也有掛掉的可能,所以數據還須要持久化。在這種狀況下,ZooKeeper就成了理想的選擇。

RootRegion管理

對應HBase集羣來講,數據存儲的位置信息是記錄在元數據region,也就是RootRegion上的。每次客戶端發起新的請求,須要知道數據的位置,就會去查詢RootRegion,而RootRegion自身位置則是記錄在ZooKeeper上的(默認狀況下,是記錄在ZooKeeper的/hbase/meta-region-server節點中)。當RootRegion發生變化,好比Region的手工移動、從新負載均衡或RootRegion所在服務器發生了故障等是,就可以經過ZooKeeper來感知到這一變化並作出一系列相應的容災措施,從而保證客戶端老是可以拿到正確的RootRegion信息。

Region管理

HBase裏的Region會常常發生變動,這些變動的緣由來自於系統故障、負載均衡、配置修改、Region分裂與合併等。一旦Region發生移動,它就會經歷下線(offline)和從新上線(online)的過程。

下線期間數據是不能被訪問的,而且Region的這個狀態變化必須讓全局知曉,不然可能會出現事務性的異常。對於大的HBase集羣來講,Region的數量可能會多達十萬級別,甚至更多,這樣規模的Region狀態管理交給ZooKeeper來作也是一個很好的選擇。

分佈式SplitWAL任務管理

當某臺RegionServer服務器掛掉時,因爲總有一部分新寫入的數據尚未持久化到HFile中,所以在遷移該RegionServer的服務時,一個重要的工做就是從WAL中恢復這部分還在內存中的數據,而這部分工做最關鍵的一步就是SplitWAL,即HMaster須要遍歷該RegionServer服務器的WAL,並按Region切分紅小塊移動到新的地址下,並進行日誌的回放(replay)

因爲單個RegionServer的日誌量相對龐大(可能有上千個Region,上GB的日誌),而用戶又每每但願系統可以快速完成日誌的恢復工做。所以一個可行的方案是將這個處理WAL的任務分給多臺RegionServer服務器來共同處理,而這就又須要一個持久化組件來輔助HMaster完成任務的分配。當前的作法是,HMaster會在ZooKeeper上建立一個SplitWAL節點(默認狀況下,是/hbase/SplitWAL節點),將「哪一個RegionServer處理哪一個Region」這樣的信息以列表的形式存放到該節點上,而後由各個RegionServer服務器自行到該節點上去領取任務並在任務執行成功或失敗後再更新該節點的信息,以通知HMaster繼續進行後面的步驟。ZooKeeper在這裏擔負起了分佈式集羣中相互通知和信息持久化的角色。

小結:

以上就是一些HBase中依賴ZooKeeper完成分佈式協調功能的典型場景。但事實上,HBase對ZooKeepr的依賴還不止這些,好比HMaster還依賴ZooKeeper來完成Table的enable/disable狀態記錄,以及HBase中幾乎全部的元數據存儲都是放在ZooKeeper上的。

因爲ZooKeeper出色的分佈式協調能力及良好的通知機制,HBase在各版本的演進過程當中愈來愈多地增長了ZooKeeper的應用場景,從趨勢上來看二者的交集愈來愈多。HBase中全部對ZooKeeper的操做都封裝在了org.apache.hadoop.hbase.zookeeper這個包中,感興趣的同窗能夠自行研究。

相關文章
相關標籤/搜索