Zookeeper

一、What

  • 一個主從架構(gòu)的分布式框架
  • 給分布式框架提供協(xié)調(diào)服務(wù)(service)

作用

  • 提供簡版文件系統(tǒng)來存儲數(shù)據(jù)
  • 維護(hù)和監(jiān)控存儲的數(shù)據(jù)狀態(tài)變化,通過監(jiān)控數(shù)據(jù)狀態(tài)變化達(dá)到基于數(shù)據(jù)的集群管理
  • 主要用來解決分布式集群中應(yīng)用系統(tǒng)的一致性問題

應(yīng)用場景

1. 主備切換
2. 節(jié)點(diǎn)的上下線感知
3. 統(tǒng)一命名服務(wù)
4. 狀態(tài)同步服務(wù)
5. 集群管理
6. 分布式應(yīng)用配置管理

二、基本概念

ZooKeeper=簡版文件系統(tǒng)(Znode)+原語+通知機(jī)制(Watcher)

  • ZK文件系統(tǒng)
    基于類似于文件系統(tǒng)的目錄節(jié)點(diǎn)樹方式的數(shù)據(jù)存儲
  • 原語
    提供類linux指令進(jìn)行操作
  • Watcher(監(jiān)聽器)

數(shù)據(jù)節(jié)點(diǎn)ZNode

數(shù)據(jù)節(jié)點(diǎn)本質(zhì)就是目錄

持久節(jié)點(diǎn) 臨時節(jié)點(diǎn)
非有序節(jié)點(diǎn) create create -e
有序節(jié)點(diǎn) create -s create -s -e
  1. 持久節(jié)點(diǎn)(無序)
    節(jié)點(diǎn)創(chuàng)建以后,即便連接斷開,除非主動刪除,不然會一直存在
  2. 持久節(jié)點(diǎn)(有序)
    創(chuàng)建節(jié)點(diǎn)的時候加上 -s ,會默認(rèn)的在目錄后加上數(shù)字
    防止同一目錄創(chuàng)建同名ZNode導(dǎo)致失敗
  3. 臨時節(jié)點(diǎn)(無序)
    節(jié)點(diǎn)創(chuàng)建以后,一旦連接斷開會自動刪除
    創(chuàng)建節(jié)點(diǎn)的時候通過 -t 指定
  4. 持久節(jié)點(diǎn)(有序)
    同上

會話

與zk交互時會建立TCP長連接,稱為會話
建立會話后,如果超過SessionTimeout時間,兩者間沒有通信,會話超時
特點(diǎn):同一個會話里執(zhí)行的指令是有序的;不同會話之間的指令是無序的

事務(wù)zxid

  • 每個對數(shù)據(jù)的增刪改操作都會生成一個對應(yīng)的zxid
  • zxid全局唯一,并且是自增的
  • zxid通常是由64位數(shù)字,epoch+counter組成

Watch監(jiān)視與通知

方式一(輪詢):ZooKeeper以遠(yuǎn)程服務(wù)的方式,被客戶端訪問;客戶端以輪詢的方式獲得znode數(shù)據(jù),效率會比較低(代價比較大)

方式二(通知機(jī)制):客戶端在znode上注冊一個Watcher監(jiān)視器,當(dāng)znode上數(shù)據(jù)出現(xiàn)變化,watcher監(jiān)測到此變化,通知客戶端

  1. Watch作用流程
  • 客戶端在服務(wù)器端,注冊的事件監(jiān)聽器
  • watcher用于監(jiān)聽znode上的某些事件
  • 比如znode數(shù)據(jù)修改、節(jié)點(diǎn)增刪等
  • 當(dāng)監(jiān)聽到事件后,watcher會觸發(fā)通知客戶端
  1. 節(jié)點(diǎn)上下線原理
    ① 節(jié)點(diǎn)1(client1)創(chuàng)建臨時節(jié)點(diǎn)
    ② 節(jié)點(diǎn)2(client2)在臨時節(jié)點(diǎn),注冊監(jiān)聽器watcher
    ③ 當(dāng)client1與zk集群斷開連接,臨時節(jié)點(diǎn)會被刪除
    ④ watcher發(fā)送消息,通知client2,臨時節(jié)點(diǎn)被刪除的事件
    用到的zk特性:Watcher+臨時節(jié)點(diǎn)
    好處:通過這種方式,檢測和被檢測系統(tǒng)不需要直接關(guān)聯(lián)(如client1與client2),而是通過ZK上的某個節(jié)點(diǎn)進(jìn)行關(guān)聯(lián),大大減少了系統(tǒng)耦合

三、HDFS HA方案

工作原理

ZooKeeper使用原子廣播協(xié)議叫做Zab(ZooKeeper Automic Broadcast)協(xié)議

  • Zab協(xié)議有兩種模式
    • 恢復(fù)模式(選主):因?yàn)閆ooKeeper是主從架構(gòu);當(dāng)ZooKeeper集群沒有主的角色leader時,從眾多服務(wù)器中選舉leader時,處于此模式
    • 廣播模式(同步):當(dāng)集群有了leader后,客戶端向ZooKeeper集群讀寫數(shù)據(jù)時,集群處于此模式
  • 為了保證事務(wù)的順序一致性,ZooKeeper采用了遞增的事務(wù)id號(zxid)來標(biāo)識事務(wù),所有提議(proposal)都有zxid

監(jiān)聽器

  • 注冊:客戶端向ZooKeeper集群注冊監(jiān)聽器

  • 監(jiān)聽事件:監(jiān)聽器負(fù)責(zé)監(jiān)聽特定的事件

  • 回調(diào)函數(shù):當(dāng)監(jiān)聽器監(jiān)聽到事件的發(fā)生后,調(diào)用注冊監(jiān)聽器時定義的回調(diào)函數(shù)

HA原理

HDFS HA方案,主要分兩部分:

①元數(shù)據(jù)同步

  • 在同一個HDFS集群,運(yùn)行兩個互為主備的NameNode節(jié)點(diǎn)。
  • 一臺為主Namenode節(jié)點(diǎn),處于Active狀態(tài),一臺為備NameNode節(jié)點(diǎn),處于Standby狀態(tài)。
  • 只有Active NameNode對外提供讀寫服務(wù),Standby NameNode會根據(jù)Active NameNode的狀態(tài)變化,在必要時切換成Active狀態(tài)。
  • JournalNode集群
    • 在主備切換過程中,新的Active NameNode必須確保與原Active NamNode元數(shù)據(jù)同步完成,才能對外提供服務(wù)
    • 所以用JournalNode集群作為共享存儲系統(tǒng);
    • 當(dāng)客戶端對HDFS做操作,會在Active NameNode中edits.log文件中作日志記錄,同時日志記錄也會寫入JournalNode集群;負(fù)責(zé)存儲HDFS新產(chǎn)生的元數(shù)據(jù)
    • 當(dāng)有新數(shù)據(jù)寫入JournalNode集群時,Standby NameNode能監(jiān)聽到此情況,將新數(shù)據(jù)同步過來
    • Active NameNode(寫入)和Standby NameNode(讀取)實(shí)現(xiàn)元數(shù)據(jù)同步
    • 另外,所有datanode會向兩個主備namenode做block report

②主備切換

  • 每個NameNode節(jié)點(diǎn)上各有一個ZKFC進(jìn)程
  • ZKFC即ZKFailoverController,作為獨(dú)立進(jìn)程存在,負(fù)責(zé)控制NameNode的主備切換
  • ZKFC會監(jiān)控NameNode的健康狀況,當(dāng)發(fā)現(xiàn)Active NameNode異常時,通過Zookeeper集群進(jìn)行namenode主備選舉,完成Active和Standby狀態(tài)的切換
    • ZKFC在啟動時,同時會初始化HealthMonitor和ActiveStandbyElector服務(wù)
    • ZKFC同時會向HealthMonitor和ActiveStandbyElector注冊相應(yīng)的回調(diào)方法(如上圖的①回調(diào)、②回調(diào))
    • HealthMonitor定時調(diào)用NameNode的HAServiceProtocol RPC接口(monitorHealth和getServiceStatus),監(jiān)控NameNode的健康狀態(tài),并向ZKFC反饋
    • ActiveStandbyElector接收ZKFC的選舉請求,通過Zookeeper自動完成namenode主備選舉
    • 選舉完成后回調(diào)ZKFC的主備切換方法對NameNode進(jìn)行Active和Standby狀態(tài)的切換

主備切換過程

  • ① 啟動NameNode,ZKFC,此時兩個NameNode的狀態(tài)都是競選狀態(tài)
  • ② 兩個ZKFC分別通過ActiveStandbyElector發(fā)起NameNode的選舉
    通過zookeeper的寫一致性以及臨時節(jié)點(diǎn)來實(shí)現(xiàn)
  • ③ 發(fā)起主備選舉的時候,ActiveStandbyElector會嘗試在zookeeper的某個目錄下創(chuàng)建一個臨時節(jié)點(diǎn),zookeeper的寫一致性會保證只有一個節(jié)點(diǎn)創(chuàng)建成功
  • ④ 創(chuàng)建成功的ActiveStandbyElector通過回調(diào)方式通知ZKFC,將對應(yīng)的NameNode切換為Active狀態(tài);創(chuàng)建失敗的也通過同樣方式將NameNode切換為Standby狀態(tài)
  • ⑤ 無論是否創(chuàng)建成功,這些ActiveStandbyElector都會監(jiān)聽那個目錄;
    當(dāng)Active NameNode對應(yīng)的HealthMonitor監(jiān)控到NameNode異常時,會告知ZKFC,ZKFC通過ActiveStandbyElector刪除所創(chuàng)建的臨時節(jié)點(diǎn),以及目錄A
    若是ZKFC是因?yàn)楫惓嚅_的連接,那么目錄A還會存在
  • ⑥ 此時處于Standby的NameNode會監(jiān)控到這個消息
    它首先會通過判斷目錄A是否存在來確認(rèn)情況
    如果是正常關(guān)閉的,則發(fā)起主備選舉,成功創(chuàng)建臨時節(jié)點(diǎn),并且將NameNode的狀態(tài)切換為Active
    如果是異常關(guān)閉的,則會
    1、通過RPC調(diào)用,試圖讓之前的Active的NameNode切換為StandBy
    2、隔離:① 發(fā)送kill指令 ② 使用hadoop的隔離方式

腦裂
在分布式系統(tǒng)中雙主現(xiàn)象又稱為腦裂,由于Zookeeper的“假死”、長時間的垃圾回收或其它原因都可能導(dǎo)致雙Active NameNode現(xiàn)象,此時兩個NameNode都可以對外提供服務(wù),無法保證數(shù)據(jù)一致性

  • 隔離
    對于生產(chǎn)環(huán)境,這種情況的出現(xiàn)是毀滅性的,必須通過自帶的隔離(Fencing)機(jī)制預(yù)防此類情況
  • 原理
    • ActiveStandbyElector成功創(chuàng)建ActiveStandbyElectorLock臨時節(jié)點(diǎn)后,額外創(chuàng)建一個ActiveBreadCrumb持久節(jié)點(diǎn)

    • ActiveBreadCurmb持久節(jié)點(diǎn)保存Active NameNode的服務(wù)器信息

    • 當(dāng)Active NameNode正常狀態(tài)下斷開與Zookeeper Session,會一并刪除臨時節(jié)點(diǎn)ActiveStandbyElectorLock和ActiveBreadCurmb持久節(jié)點(diǎn)

    • 如果是異常斷開的,那么此時臨時節(jié)點(diǎn)ActiveStandbyElectorLock不存在,但是ActiveBreadCurmb持久節(jié)點(diǎn)還存在;Standby節(jié)點(diǎn)會收到監(jiān)聽器發(fā)來的提醒將要從Standby切換成Active時,會先通過ActiveBreadCurmb里的服務(wù)器信息做隔離
      1、通過RPC調(diào)用,試圖讓之前的Active的NameNode切換為StandBy
      2、隔離(hadoop提供這兩種隔離):① 發(fā)送kill指令 ② 使用hadoop的隔離方式

      只有成功地fencing之后,選主成功的ActiveStandbyElector才會回調(diào)ZKFC的becomeActive方法transitionToActive將對應(yīng)的NameNode切換為Active,開始對外提供服務(wù)

四、Zookeeper架構(gòu)

ZooKeeper服務(wù)器四種狀態(tài):

  • looking:服務(wù)器處于尋找Leader群首的狀態(tài)

  • leading:服務(wù)器作為群首時的狀態(tài)

  • following:服務(wù)器作為follower跟隨者時的狀態(tài)

  • observing:服務(wù)器作為觀察者時的狀態(tài)

1、安其內(nèi)

全新leader選舉(重啟集群)
原則:集群超過半數(shù)的服務(wù)器啟動后,才能選出leader
選舉規(guī)則:

  1. 初始化:每個節(jié)點(diǎn)都投自己一票,然后向其他所有節(jié)點(diǎn)發(fā)送自己票的信息
  2. 交換投票信息:接收其他節(jié)點(diǎn)的選舉信息,與自己的那票進(jìn)行比較
    投票信息vote信息結(jié)構(gòu)為(serverId, zxid)
    會先比較zxid,zxid大的那臺服務(wù)器勝出(zxid越大意味存儲了更多的數(shù)據(jù))
    若是zxid相同則serverId大的那臺服務(wù)器會勝出
    比較結(jié)束后,每臺服務(wù)器會更新自己的投票信息,繼續(xù)給其他服務(wù)器發(fā)送
  3. 決定投票結(jié)果:假設(shè)服務(wù)器B接收到超過半數(shù)的票選舉自己,則自己從looking切換為leading,其他服務(wù)器從looking切換為following
  4. 當(dāng)服務(wù)器C啟動時,發(fā)現(xiàn)已有Leader,不再選舉,直接從Looking改為Following

全新leader選舉(leading掛掉或者出現(xiàn)網(wǎng)絡(luò)分區(qū))

攘其外

讀操作

  • 常見的讀取操作,如ls /查看目錄;get /zktest查詢ZNode數(shù)據(jù)
  • 讀操作
    • 客戶端先與某個zk任意一臺服務(wù)器建立Session
    • 然后,直接從此ZK服務(wù)器讀取數(shù)據(jù),并返回客戶端即可
    • 關(guān)閉Session

寫操作

  • ① 與zk任意一臺服務(wù)器建立Session建立連接
  • ② follower將寫請求轉(zhuǎn)發(fā)給leader(不執(zhí)行)
  • ③ leader收到消息后,發(fā)起proposal提案
  • ④ 每臺服務(wù)器都會收到proposal后會記錄這次操作并向leader返回同意,但不執(zhí)行
  • ⑤ 超過半數(shù)quorum同意,則leader提交commit提案,leader執(zhí)行該操作
  • ⑥ leader通知所有節(jié)點(diǎn)也commit提交該提案;所有節(jié)點(diǎn)在所在服務(wù)器執(zhí)行該操作
  • ⑦ client連接的那臺follower響應(yīng)Client

五、原理

quorum仲裁

  • 什么是仲裁quorum?
    • 發(fā)起proposal時,只要多數(shù)派同意,即可生效
  • 為什么要仲裁?
    • 多數(shù)據(jù)派不需要所有的服務(wù)器都響應(yīng),proposal就能生效
    • 提高集群的響應(yīng)速度
  • quorum數(shù)如何選擇?
    • 集群節(jié)點(diǎn)數(shù) / 2 + 1

為什么集群節(jié)點(diǎn)數(shù)強(qiáng)烈建議奇數(shù)個?
5節(jié)點(diǎn)的比6節(jié)點(diǎn)的集群

  • 容災(zāi)能力一樣,
  • quorum小,響應(yīng)快
  • 偶數(shù)個如果被網(wǎng)絡(luò)分區(qū)平分,則不能提供服務(wù)

網(wǎng)絡(luò)分區(qū)和腦裂

  • 網(wǎng)絡(luò)分區(qū):網(wǎng)絡(luò)通信故障,集群被分成了2部分
  • 腦裂:
    • 原leader處于一個分區(qū);
    • 另外一個分區(qū)選舉出新的leader
    • 集群出現(xiàn)2個leader

ZAB算法

  1. 每個節(jié)點(diǎn)都有一個計時器(150毫秒~300毫秒之間的隨機(jī)數(shù)),時間到后會發(fā)起選舉的操作

  2. 非leader節(jié)點(diǎn)會定時的向leader節(jié)點(diǎn)發(fā)送心跳,leader收到心跳后會返回信息,非leader節(jié)點(diǎn)收到這個信息后會重置計時器

  3. 當(dāng)發(fā)生網(wǎng)絡(luò)分區(qū)并且leader處于少數(shù)的那邊時,其他follower會進(jìn)行選舉,假設(shè)B服務(wù)器選舉成功,那么它會和其他follower進(jìn)行zxid的比較

    ① 假設(shè)服務(wù)器C的zkid比服務(wù)器B的少10個,那么服務(wù)器B會將這十個操作封包發(fā)給服務(wù)器C來執(zhí)行
    ② 假設(shè)服務(wù)器D的zxid比服務(wù)器B多10個,那么服務(wù)器B會讓它將這十個記錄都刪除
    做完以上操作后,服務(wù)器B才會從follower切換成leader,并且將epoch里的值進(jìn)行加1,zxid進(jìn)行重置

  4. 當(dāng)網(wǎng)絡(luò)恢復(fù)了之后,舊leader比較路徑下的epoch值的時候,發(fā)現(xiàn)已經(jīng)有新的leader產(chǎn)生,會將自己切換成follower,并且進(jìn)行數(shù)據(jù)的同步

狀態(tài)同步

完成選舉后,zk之間會進(jìn)行狀態(tài)同步操作

    1. leader構(gòu)建NEWLEADER封包,包含leader最大zxid值,廣播給其他follower
    1. follower收到后會跟自己最大zxid比較,若是比它小則進(jìn)行同步操作
    1. leader給每個需要同步的follower創(chuàng)建LearnerHandler同步線程,負(fù)責(zé)進(jìn)行同步操作
    1. leader主線程等待LearnerHandler線程處理結(jié)果
    1. 只有當(dāng)大部分follower完成同步,該集群才對外提供服務(wù),相應(yīng)寫請求
    1. LearnerHandler線程處理邏輯
      1. 接收follower封包FOLLOWERINFO,包含此follower最大zxid(代稱f-max-zxid)
      1. f-max-zxid與leader最大zxid(代稱l-max-zxid)比較
      1. 若相等,說明當(dāng)前follower是最新的
      1. 另外,若在判斷期間,有沒有新提交的proposal
        1. 如果有,那么會發(fā)送DIFF封包將有差異的數(shù)據(jù)同步過去.同時將follower沒有的數(shù)據(jù)逐個發(fā)送COMMIT封包給follower要求記錄下來.
        1. 如果follower數(shù)據(jù)id更大,那么會發(fā)送TRUNC封包告知截除多余數(shù)據(jù).
        1. 如果這一階段內(nèi)沒有提交的提議值,直接發(fā)送SNAP封包將快照同步發(fā)送給follower.
      1. 以上消息完畢之后,發(fā)送UPTODATE封包告知follower當(dāng)前數(shù)據(jù)就是最新的了
      1. 再次發(fā)送NEWLEADER封包宣稱自己是leader,等待follower的響應(yīng).

分布式鎖

    1. 所有需要獲取鎖的引用都在 /locker路徑下創(chuàng)建一個有序臨時節(jié)點(diǎn)
    1. 該路徑下序號最小的應(yīng)用獲取該鎖,其他應(yīng)用分別監(jiān)視比自己小一點(diǎn)的那個ZNode
    1. 當(dāng)序號最小的那個應(yīng)用操作完后,斷開連接時,比它稍微大一點(diǎn)的那個應(yīng)用會獲取鎖

分布式鎖主要是應(yīng)用了zk的一致性、臨時節(jié)點(diǎn)、watch監(jiān)視器這幾個特性來保證的

WHO

  1. NameNode使用ZooKeeper實(shí)現(xiàn)高可用.
  2. Yarn ResourceManager使用ZooKeeper實(shí)現(xiàn)高可用.
  3. 利用ZooKeeper對HBase集群做高可用配置
  4. kafka使用ZooKeeper(僅限0.9以及之前版本)
    • 保存消息消費(fèi)信息比如offset.
    • 用于檢測崩潰
    • 主題topic發(fā)現(xiàn)
    • 保持主題的生產(chǎn)和消費(fèi)狀態(tài)

常用操作

# 使用ZooKeeper自帶的腳本,連接ZooKeeper的服務(wù)器
zkCli.sh -server node01:2181,node02:2181,node03:2181

#創(chuàng)建節(jié)點(diǎn),并指定數(shù)據(jù)(必須要指定數(shù)據(jù))
create /kkb kkb
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容