Zookeeper知识点详解
Zookeeper知識(shí)點(diǎn)詳解
目錄
ZooKeeper 集群原理
ZooKeeper 分布式鎖
ZooKeeper 分布式事務(wù)
ZooKeeper 選舉原理
Paxos 協(xié)議
ZAB 協(xié)議
ZooKeeper 會(huì)話管理
ZooKeeper 的 Watcher 機(jī)制
ZooKeeper 的應(yīng)用場(chǎng)景
1. ZooKeeper 集群原理
關(guān)于 ZooKeeper,官網(wǎng)給出的一句話定義:
A Distributed Coordination Service for Distributed Applications
簡(jiǎn)單地說,ZooKeeper 是一個(gè)分布式應(yīng)用程序協(xié)調(diào)服務(wù)。
ZooKeeper 集群設(shè)計(jì)原則:
2. ZooKeeper 分布式鎖
ZooKeeper 分布式鎖有兩個(gè)核心要素:臨時(shí)有序節(jié)點(diǎn)和 Watcher 事件監(jiān)聽。
首先,什么是臨時(shí)有序節(jié)點(diǎn)?ZK 底層數(shù)據(jù)結(jié)構(gòu)是一棵樹,由節(jié)點(diǎn) Znode 組成,Znode 分四種類型:
其次,什么是 Watcher?簡(jiǎn)單地說,Watcher 是一種事件監(jiān)聽機(jī)制??蛻舳嗽谧x寫數(shù)據(jù)時(shí),可以對(duì) ZK 節(jié)點(diǎn)注冊(cè)事件監(jiān)聽器 Watcher。一旦 ZK 節(jié)點(diǎn)數(shù)據(jù)或結(jié)構(gòu)變化,ZooKeeper 會(huì)觸發(fā)相應(yīng)的事件 WatchEvent,通知客戶端 Watcher 接口的回調(diào)方法 process()。
public interface Watcher {abstract public void process(WatchedEvent event); }接下來,我們看看什么是分布式鎖?相對(duì)于 JVM 鎖,分布式鎖的特點(diǎn)是跨 JVM 的,這兩張圖可以說明。
下面,舉例說明 ZooKeeper 是如何實(shí)現(xiàn)分布式鎖的。
假設(shè)有三個(gè)進(jìn)程同時(shí)訪問一個(gè)臨界區(qū)資源,我們需要 ZooKeeper 分布式鎖做并發(fā)控制,同一時(shí)刻只允許同一個(gè)進(jìn)程訪問。我們把三個(gè)進(jìn)程當(dāng)成三個(gè) ZK 的客戶端,分別創(chuàng)建三個(gè) ZK 臨時(shí)有序節(jié)點(diǎn):Lock1、Lock2、Lock3,掛在 ParentLock 節(jié)點(diǎn)下面,其中 Lock1 節(jié)點(diǎn)編號(hào)最小,Lock3 節(jié)點(diǎn)編號(hào)最大。已知 Client1 獲取鎖,Client2 與 Client3 分別注冊(cè) Watch 監(jiān)聽器,其中 Client2 監(jiān)聽 Lock1 節(jié)點(diǎn),Client3 監(jiān)聽 Lock2 節(jié)點(diǎn)。
假設(shè) Client1 完成任務(wù),斷開連接,釋放鎖,ZK 自動(dòng)刪除 Lock1 節(jié)點(diǎn),產(chǎn)生事件,觸發(fā) Client2 的監(jiān)聽器 Watcher 回調(diào)。此時(shí),Client2 會(huì)再次查詢 ParentLock 下面的所有節(jié)點(diǎn),確認(rèn)自己創(chuàng)建的節(jié)點(diǎn) Lock2 是否為最小節(jié)點(diǎn),如果是,則 Client2 順利成章獲取了鎖。
最后看一下獲取鎖的代碼:
3. ZooKeeper 分布式事務(wù)
ZooKeeper 實(shí)現(xiàn)分布式事務(wù),類似于兩階段提交,總共分四個(gè)步驟:
步驟 #1:客戶端先向 ZK 節(jié)點(diǎn)發(fā)送寫請(qǐng)求。
步驟 #2:ZK 節(jié)點(diǎn)將寫請(qǐng)求轉(zhuǎn)發(fā)給 Leader 節(jié)點(diǎn),Leader 廣播給集群要求投票,等待確認(rèn)。
步驟 #3:Leader 收到確認(rèn),統(tǒng)計(jì)投票,票數(shù)過半則提交事務(wù)。
步驟 #4:事務(wù)提交成功后,ZK 節(jié)點(diǎn)告知客戶端。
4. ZooKeeper 選舉原理
先來明確一下概念:
sid(serverId):比如有三臺(tái)服務(wù)器,編號(hào)分別是 1、2、3。編號(hào)越大,在選擇算法中的權(quán)重越大。
zxid(最新的事務(wù) ID ):ID 值越大說明數(shù)據(jù)越新,在選舉算法中數(shù)據(jù)越新權(quán)重越大。
epoch (邏輯時(shí)鐘 ):同一輪投票的邏輯時(shí)鐘值是相同的。每投完一次票這個(gè)數(shù)據(jù)就會(huì)增加。
選舉狀態(tài):LOOKING 競(jìng)選;FOLLOWING 隨從,投票;OBSERVING 觀察,不投票;LEADING 領(lǐng)導(dǎo)者。
vote_sid:對(duì)方投票推舉 Leader 的服務(wù)器 sid。
vote_zxid:對(duì)方投票推舉 Leader 的服務(wù)器 zxid。
self_sid:當(dāng)前服務(wù)器的 sid。
self_zxid:當(dāng)前服務(wù)器的 zxid。
規(guī)則如下:
我們假設(shè) ZooKeeper 集群由 5 臺(tái)機(jī)器組成,sid 分別為 1、2、3、4 和 5,zxid 分別為 9、9、9、8 和 8,2 號(hào)機(jī)器是 Leader。某一時(shí)刻,1 號(hào)和 2 號(hào)機(jī)器宕機(jī),因此集群開始進(jìn)行 Leader 選舉。
第一輪投票,epoch=1。
由于機(jī)器彼此不知對(duì)方的狀態(tài),因此每臺(tái)機(jī)器都將票投給自己。投票情況分別為:(3, 9)、(4, 8)和(5, 8)。每臺(tái)機(jī)器都把投票發(fā)出后,同時(shí)也會(huì)接收到來自另外兩臺(tái)機(jī)器的投票。
第二輪投票,epoch=2。
對(duì)干 3 號(hào)機(jī)器,接收(4, 8)和(5, 8)兩張投票,發(fā)現(xiàn) self_zxid=9 大于 vote_zxid=8,因此無需變更。
對(duì)于 4 號(hào)機(jī)器,接收(3, 9)和(5, 8)兩張投票,發(fā)現(xiàn) self_zxid=8 小于 vote_zxid=9,認(rèn)可并變更投票為(3, 9),再次將這張票投出去。
5 號(hào)機(jī)器與 4 號(hào)類似,認(rèn)可并變更投票為(3, 9),再次將這張票投出去。
兩輪投票過后,投票桶的票數(shù)為 3,已過半數(shù),3 號(hào)晉升為 Leader,其余退化為 Follower。
5. Paxos 協(xié)議
ZooKeeper 分布式一致性算法的原型,就是 Paxos 協(xié)議。下面簡(jiǎn)單分析一下 Paxos 協(xié)議。Paxos 中有三類角色 Proposer、Acceptor 及 Learner,相當(dāng)于 ZooKeeper 集群中的 Leader、Follower 和 Observer。
簡(jiǎn)單地說,Paxos 的原理是:Proposer 將發(fā)起提案(value)給所有 Accpetor,超過半數(shù) Accpetor 獲得批準(zhǔn)后,Proposer 將提案寫入 Accpetor 內(nèi),最終所有 Accpetor 獲得一致性的確定性取值,且后續(xù)不允許再修改。
這 4 類消息對(duì)應(yīng)于 Paxos 算法的兩個(gè)階段 4 個(gè)過程,如下圖:
Paxos 在原作者的 Paxos Made Simple 中內(nèi)容是比較精簡(jiǎn)的:
Phase 1
(a) A proposer selects a proposal number n and sends a prepare request with number n to a majority of acceptors.
(a) Proposer 選擇一個(gè)提議編號(hào) n,向超半數(shù) Acceptor 廣播 Prepare(n)請(qǐng)求。
(b) If an acceptor receives a prepare request with number n greater than that of any prepare request to which it has already responded, then it responds to the request with a promise not to accept any more proposals numbered less than n and with the highest-numbered pro-posal (if any) that it has accepted.
(b) Acceptor 接收到 Prepare(n)請(qǐng)求,若提議編號(hào) n 比之前接收的 Prepare 請(qǐng)求都要大,則承諾將不會(huì)接收提議編號(hào)比 n 小的提議,并且?guī)现?Accept 的提議中編號(hào)小于 n 的最大的提議,否則不予理會(huì)。
Phase 2
(a) If the proposer receives a response to its prepare requests (numbered n) from a majority of acceptors, then it sends an accept request to each of those acceptors for a proposal numbered n with a value v , where v is the value of the highest-numbered proposal among the responses, or is any value if the responses reported no proposals.
(a) Proposer 得到了 Acceptor 響應(yīng),如果未超過半數(shù) Accpetor 響應(yīng),直接轉(zhuǎn)為提議失敗;如果超過多數(shù) Acceptor 的承諾,又分為不同情況:如果所有 Acceptor 都未接收過值(都為 null),那么向所有的 Acceptor 發(fā)起自己的值和提議編號(hào) n;如果有部分 Acceptor 接收過值,那么從所有接受過的值中選擇對(duì)應(yīng)的提議編號(hào)最大的作為提議的值,提議編號(hào)仍然為 n。但此時(shí) Proposer 就不能提議自己的值,只能信任 Acceptor 通過的值 v,維護(hù)一但獲得確定性取值就不能更改原則;
(b) If an acceptor receives an accept request for a proposal numbered n, it accepts the proposal unless it has already responded to a prepare request having a number greater than n.
(b) Acceptor 接收到提議后,如果該提議版本號(hào)不等于自身保存記錄的版本號(hào)(第一階段記錄的),不接受該請(qǐng)求,相等則寫入本地。
6. ZAB 協(xié)議
ZAB 是 ZooKeeper Atomic Broadcast 簡(jiǎn)稱,是 ZooKeeper 實(shí)現(xiàn)一致性的理論依據(jù)。原文寫得非常簡(jiǎn)單,只有非?;\統(tǒng)的框架,沒有細(xì)節(jié)。
ZAB 分為兩個(gè)部分:Broadcast 和 Recovery。
當(dāng)系統(tǒng)啟動(dòng)或者leader服務(wù)器出現(xiàn)故障等現(xiàn)象時(shí),進(jìn)入故障恢復(fù)模式。將會(huì)開啟新的一輪的選舉。選舉產(chǎn)生的leader會(huì)與過半的follower進(jìn)行同步,保持?jǐn)?shù)據(jù)一致。當(dāng)同步結(jié)束后,退出恢復(fù)模式,進(jìn)入消息廣播模式。當(dāng)一臺(tái)遵循ZAB協(xié)議的服務(wù)器啟動(dòng)后,如果檢測(cè)到有l(wèi)eader在廣播消息,會(huì)自動(dòng)進(jìn)入恢復(fù)模式,當(dāng)其完成與leader的同步以后,進(jìn)入消息廣播模式。如果集群中的非leader 節(jié)點(diǎn)收到客戶端請(qǐng)求,非leader會(huì)先將請(qǐng)求發(fā)送到leader服務(wù)器。
先說一下 Broadcast 廣播機(jī)制。
Leader 接受所有寫請(qǐng)求;超過半數(shù) Follower 進(jìn)行 Ack 確認(rèn)后,Leader 發(fā)送 Commit。類似于簡(jiǎn)化版的二階段協(xié)議。Leader 用 zxid 保證消息的順序性。Follower 存入硬盤后 Ack,在接收到 Commit 后開始服務(wù) Client。Client 讀 in-memory 的數(shù)據(jù)。
再說一下 Recovery 恢復(fù)機(jī)制。
剛剛我們說消息廣播過程中,Leader 崩潰(崩潰即 Leader 失去與過半 Follwer 的聯(lián)系)怎么辦?還能保證數(shù)據(jù)一致嗎?
針對(duì)這些問題,ZAB 定義了 2 個(gè)原則:
- ZAB 協(xié)議確保那些已經(jīng)在 Leader 提交的事務(wù)最終會(huì)被所有服務(wù)器提交。
- ZAB 協(xié)議確保丟棄那些只在 Leader 提出/復(fù)制,但沒有提交的事務(wù)。
7. ZooKeeper 會(huì)話管理
Session 指的是 ZooKeeper 服務(wù)器與客戶端會(huì)話,換句話說,指的是客戶端和服務(wù)端之間的一次 TCP 長連接。
客戶端啟動(dòng)時(shí),會(huì)與服務(wù)器建立 TCP 連接,此時(shí)客戶端會(huì)話的生命周期就開始了。通過 Session,客戶端能夠用 ping-pong 心跳檢測(cè)與服務(wù)端保持連接,客戶端可以向 ZK 發(fā)送請(qǐng)求并接受響應(yīng),同時(shí) ZK 還能通過 Watch 向客戶端推送通知。
Session 的 sessionTimeout 參數(shù)用來設(shè)置一個(gè)客戶端會(huì)話的超時(shí)時(shí)間。由于網(wǎng)絡(luò)故障或客戶端主動(dòng)斷開連接時(shí),只要在 sessionTimeout 有效期內(nèi)重連任意機(jī)器,那么此前創(chuàng)建的會(huì)話仍然有效。
為客戶端創(chuàng)建會(huì)話之前,服務(wù)端首先會(huì)為每一個(gè)客戶端分配一個(gè) sessionID。由于 sessionID 是 ZooKeeper 會(huì)話的重要標(biāo)識(shí),許多與會(huì)話相關(guān)的運(yùn)行機(jī)制都是基于這個(gè) sessionID 的,因此無論是哪臺(tái)服務(wù)器為客戶端分配 sessionID,都要?jiǎng)?wù)必保證全局唯一。
8. ZooKeeper 的 Watcher 機(jī)制
Watcher 是 ZooKeeper 的一個(gè)重要特性。ZooKeeper 允許用戶在指定的節(jié)點(diǎn)上注冊(cè)一些 Watcher,并且在一些特定事件觸發(fā)的時(shí)候,ZooKeeper 服務(wù)端會(huì)將事件通知到感興趣的客戶端上,該機(jī)制是 ZooKeeper 實(shí)現(xiàn)分布式協(xié)調(diào)服務(wù)的重要特性。
public interface Watcher {abstract public void process(WatchedEvent event); }ZooKeeper 的 Watcher 有幾個(gè)特點(diǎn):
- 一次性:一旦一個(gè) Watcher 被觸發(fā),ZooKeeper 就會(huì)將其從相應(yīng)的存儲(chǔ)中移除,所以使用時(shí)要反復(fù)注冊(cè)。
- 客戶端串行:執(zhí)行 Watcher 回調(diào)的過程是一個(gè)串行執(zhí)行的過程,從而保證了順序。
- 輕量:客戶端向服務(wù)端注冊(cè) Watcher 的時(shí)候,并不會(huì)把客戶端真實(shí)的 Watcher 對(duì)象實(shí)體傳遞到服務(wù)端,僅僅是在客戶端請(qǐng)求中使用 boolean 類型屬性進(jìn)行了標(biāo)記。Watcher 通知非常簡(jiǎn)單,只會(huì)告訴客戶端發(fā)生了事件,而不會(huì)說明事件的具體內(nèi)容。
9. ZooKeeper 的應(yīng)用場(chǎng)景
發(fā)布/訂閱
應(yīng)用啟動(dòng)時(shí)主動(dòng)去 ZooKeeper 獲取配置信息,并注冊(cè)一個(gè) Watcher 監(jiān)聽配置發(fā)生變更時(shí),ZooKeeper 服務(wù)端會(huì)通知所有訂閱的客戶端,客戶端收到通知后,主動(dòng)到服務(wù)端獲取最新數(shù)據(jù)。
全局唯一
ID 利用順序節(jié)點(diǎn)的特性,創(chuàng)建一個(gè)順序節(jié)點(diǎn),根據(jù)返回的完整節(jié)點(diǎn)名,作為 ID 即可。
Master 選舉
- 開始選舉,即所有機(jī)器都作為 ZooKeeper 向 ZooKeeper 集群請(qǐng)求創(chuàng)建一個(gè)臨時(shí)節(jié)點(diǎn),成功創(chuàng)建該節(jié)點(diǎn)的機(jī)器,成為 Master。
- 其他創(chuàng)建失敗的客戶端對(duì)應(yīng)的機(jī)器,都會(huì)在該節(jié)點(diǎn)上注冊(cè)一個(gè) Watcher,用于監(jiān)控當(dāng)前的 Master 機(jī)器是否存活。
- 一旦發(fā)現(xiàn)當(dāng)前的 Master 掛了(即收到 Watcher 事件通知節(jié)點(diǎn)被刪除),則重新選舉。
分布式鎖
- 排他鎖:和 Master 選舉類似,利用臨時(shí)節(jié)點(diǎn)的特性。創(chuàng)建臨時(shí)節(jié)點(diǎn)成功的客戶端獲得鎖,客戶端意外掛掉則臨時(shí)節(jié)點(diǎn)被自動(dòng)刪除或者是正常結(jié)束業(yè)務(wù)邏輯然后主動(dòng)刪除節(jié)點(diǎn),此時(shí) ZooKeeper 會(huì)通知其他客戶端再次爭(zhēng)奪鎖。
- 共享鎖:利用順序節(jié)點(diǎn)的特性。對(duì)于讀寫請(qǐng)求,分別創(chuàng)建臨時(shí)順序節(jié)點(diǎn)。下面重要的是判斷讀寫順序——對(duì)于讀請(qǐng)求,如果有比自己序號(hào)小的寫請(qǐng)求,則進(jìn)入等待,否則執(zhí)行讀取邏輯;對(duì)于寫請(qǐng)求,如果自己不是最小的序號(hào),則進(jìn)入等待。
總結(jié)
以上是生活随笔為你收集整理的Zookeeper知识点详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: solr中文搜索倒排索引和数据存储结构
- 下一篇: zookeeper常见问题总结