Zookeeper的核心原理

一. Zookeeper設(shè)計(jì)思想:

類似于前面我們簡(jiǎn)單說(shuō)了Zookeeper可能解決的問(wèn)題,例如類似于實(shí)現(xiàn)分布式鎖,控制任務(wù)執(zhí)行

但是這里也會(huì)發(fā)現(xiàn)會(huì)有很多其他隱形問(wèn)題.Zookeeper設(shè)計(jì)時(shí)就是為了解決了這些問(wèn)題.

1. 防止單點(diǎn)故障

要防止 zookeeper 這個(gè)中間件的單點(diǎn)故障,那么肯定要做集群。而且這個(gè)集群如果要滿足高性能要求的話,還得是一個(gè)高性能高可用的集群。

  • 高性能意味著這個(gè)集群能夠分擔(dān)客戶端的請(qǐng)求流量
  • 高可用意味著集群中的某一個(gè)節(jié)點(diǎn)宕機(jī)以后,不影響整個(gè)集群的數(shù)據(jù)和繼續(xù)提供服務(wù)的可能性。

簡(jiǎn)單說(shuō)就是橫向擴(kuò)容,縱向熱備.
需求1 :.這個(gè)中間件需要考慮到集群,而且這個(gè)集群還需要分?jǐn)偪蛻舳说恼?qǐng)求流量

2.如果要滿足高性能

要保證高性能,就需要保證我們?nèi)我庹?qǐng)求打到任意結(jié)點(diǎn)上都會(huì)有相同的反饋結(jié)果.進(jìn)一步說(shuō)明我們需要保證每個(gè)節(jié)點(diǎn)都能接收到請(qǐng)求,并且每個(gè)節(jié)點(diǎn)的數(shù)據(jù)都必須要保持一致。要實(shí)現(xiàn)各個(gè)節(jié)點(diǎn)的數(shù)據(jù)一致性,就需要 一個(gè) leader 節(jié)點(diǎn)負(fù)責(zé)協(xié)調(diào)和數(shù)據(jù)同步操作。這個(gè)我想大家都知道,如果在這樣一個(gè)集群中沒(méi)有 leader 節(jié)點(diǎn),每個(gè)節(jié)點(diǎn)都可以接收所有請(qǐng)求,那么這個(gè)集群的數(shù)據(jù)同步的復(fù)雜度是非常大。
需求2:所以這個(gè)集群中涉及到數(shù)據(jù)同步以及會(huì)存在leader 節(jié)點(diǎn),用來(lái)保證數(shù)據(jù)一致性

3.如果要滿足高可用

既如何在眾多節(jié)點(diǎn)中選舉出 leader 節(jié)點(diǎn),以及l(fā)eader 宕機(jī)以后以后,如何恢復(fù)呢,如何正常保證使用呢?

需求3 :結(jié)論:所以 zookeeper 用了基于 paxos 理論所衍生出來(lái)的 ZAB 協(xié)議

4. leader 節(jié)點(diǎn)如何和其他節(jié)點(diǎn)保證數(shù)據(jù)一致性,并且要求是強(qiáng)一致的。

在分布式系統(tǒng)中,每一個(gè)機(jī)器節(jié)點(diǎn)雖然都能夠明確知道自己進(jìn)行的事務(wù)操作過(guò)程是成功和失敗,但是卻無(wú)法直接獲取其他分布式節(jié)點(diǎn)的操作結(jié)果。
所以當(dāng)一個(gè)事務(wù)操作涉及到跨節(jié)點(diǎn)的時(shí)候,就需要用到分布式事務(wù),分布式事務(wù)的數(shù)據(jù)一致性協(xié)議有 2PC 協(xié)議和3PC 協(xié)議

二 . 保證Zookeeper解決問(wèn)題的相關(guān)功能設(shè)計(jì)基礎(chǔ)

1.關(guān)于 2PC 提交(Two Phase Commitment Protocol)

當(dāng)一個(gè)事務(wù)操作需要跨越多個(gè)分布式節(jié)點(diǎn)的時(shí)候,為了保持事務(wù)處理的 ACID特性,就需要引入一個(gè)“協(xié)調(diào)者”(TM)來(lái)統(tǒng)一調(diào)度所有分布式節(jié)點(diǎn)的執(zhí)行邏輯,這些被調(diào)度的分布式節(jié)點(diǎn)被稱為 AP。TM 負(fù)責(zé)調(diào)度 AP 的行為,并最終決定這些 AP 是否要把事務(wù)真正進(jìn)行提交;因?yàn)檎麄€(gè)事務(wù)是分為兩個(gè)階段提交,所以叫 2pc

階段一:提交事務(wù)請(qǐng)求(投票)
  1. 事務(wù)詢問(wèn)
    協(xié)調(diào)者向所有的參與者發(fā)送事務(wù)內(nèi)容,詢問(wèn)是否可以執(zhí)行事
    務(wù)提交操作,并開(kāi)始等待各參與者的響應(yīng)
  2. 執(zhí)行事務(wù)
    各個(gè)參與者節(jié)點(diǎn)執(zhí)行事務(wù)操作,并將 Undo 和 Redo 信息記
    錄到事務(wù)日志中,盡量把提交過(guò)程中所有消耗時(shí)間的操作和
    準(zhǔn)備都提前完成確保后面 100%成功提交事務(wù)
  3. 各個(gè)參與者向協(xié)調(diào)者反饋事務(wù)詢問(wèn)的響應(yīng)
    如果各個(gè)參與者成功執(zhí)行了事務(wù)操作,那么就反饋給參與者
    yes 的響應(yīng),表示事務(wù)可以執(zhí)行;如果參與者沒(méi)有成功執(zhí)行
    事務(wù),就反饋給協(xié)調(diào)者 no 的響應(yīng),表示事務(wù)不可以執(zhí)行,
    上面這個(gè)階段有點(diǎn)類似協(xié)調(diào)者組織各個(gè)參與者對(duì)一次事務(wù)
    操作的投票表態(tài)過(guò)程,因此 2pc 協(xié)議的第一個(gè)階段稱為“投
    票階段”,即各參與者投票表名是否需要繼續(xù)執(zhí)行接下去的
    事務(wù)提交操作。
階段二:執(zhí)行事務(wù)提交

在這個(gè)階段,協(xié)調(diào)者會(huì)根據(jù)各參與者的反饋情況來(lái)決定最終是
否可以進(jìn)行事務(wù)提交操作,正常情況下包含兩種可能:執(zhí)行事務(wù)、
中斷事務(wù)

2. zookeeper 的集群

在 zookeeper 中,客戶端會(huì)連接到 zookeeper 集群中的一個(gè)節(jié)點(diǎn)

  • 如果是讀請(qǐng)求,就直接從當(dāng)前節(jié)點(diǎn)中讀取數(shù)據(jù)
  • 如果是寫(xiě)請(qǐng)求,那么請(qǐng)求會(huì)被轉(zhuǎn)發(fā)給 leader 提交事務(wù),然后 leader 會(huì)廣播事務(wù),只要有超過(guò)半數(shù)節(jié)點(diǎn)寫(xiě)入成功,那么寫(xiě)請(qǐng)求就會(huì)被提交(類 2PC 事務(wù)),其實(shí)這里也是為什么參與投票的結(jié)點(diǎn)數(shù)必須是2N+1最佳的原因之一.

所有事務(wù)請(qǐng)求必須由一個(gè)全局唯一的服務(wù)器來(lái)協(xié)調(diào)處理,這個(gè)服務(wù)器就是 Leader 服務(wù)器其他的服務(wù)器就是follower。

leader 服務(wù)器把客戶端的寫(xiě)請(qǐng)求轉(zhuǎn)化成一個(gè)事務(wù) Proposal(提議),并把這個(gè) Proposal 分發(fā)給集群中的所有 Follower 服務(wù)器。之后 Leader 服務(wù)器需要等待所有Follower 服務(wù)器的反饋,一旦超過(guò)半數(shù)的 Follower 服務(wù)器進(jìn)行了正確的反饋ACK,那么 Leader 就會(huì)再次向所有的Follower 服務(wù)器發(fā)送 Commit 消息要求各個(gè) follower 節(jié)點(diǎn)對(duì)前面的一個(gè) Proposal 進(jìn)行提交;

集群重的角色
  • Leader 角色
    Leader 服務(wù)器是整個(gè) zookeeper 集群的核心,主要的工作任務(wù)有兩項(xiàng)

    1. 事物請(qǐng)求的唯一調(diào)度和處理者,保證集群事物處理的順序性**
    2. 集群內(nèi)部各服務(wù)器的調(diào)度者
  • Follower 角色
    Follower 角色的主要職責(zé)是

    1. 處理客戶端非事物請(qǐng)求轉(zhuǎn)發(fā)事物請(qǐng)求給 leader 服務(wù)器
    2. 參與事物請(qǐng)求 Proposal 的投票(需要半數(shù)以上服務(wù)器
      通過(guò)才能通知 leader commit 數(shù)據(jù); Leader 發(fā)起的提案,
      要求 Follower 投票)
    3. 參與 Leader 選舉的投票
  • Observer 角色
    Observer 是 zookeeper3.3 開(kāi)始引入的一個(gè)全新的服務(wù)器
    角色,從字面來(lái)理解,該角色充當(dāng)了觀察者的角色。
    觀察 zookeeper 集群中的最新?tīng)顟B(tài)變化并將這些狀態(tài)變化
    同步到 observer 服務(wù)器上。

    Observer 的工作原理與follower 角色基本一致
    而它和 follower 角色唯一的不同在于 observer 不參與任何形式的投票
    ,包括事物請(qǐng)求Proposal的投票和leader選舉的投票。(看源碼就知道了 坐標(biāo)FastLeaderElection.java)
    簡(jiǎn)單來(lái)說(shuō),observer服務(wù)器只提供非事物請(qǐng)求服務(wù),通常在于不影響集群事物
    處理能力的前提下提升集群非事物處理的能力

為什么會(huì)有observer這種服務(wù)器存在?
由于選舉需要進(jìn)行網(wǎng)絡(luò)IO,我們的leader必須經(jīng)過(guò)全部IO結(jié)束才能決定是否提交事務(wù)或者進(jìn)行選舉,這將會(huì)拉低效率,故出現(xiàn)了Observer這種單處理不選舉的服務(wù)器類型.

集群組成

通常 zookeeper 是由 2n+1 臺(tái) server 組成,每個(gè) server 都知道彼此的存在
對(duì)于 2n+1 臺(tái) server,只要有 n+1 臺(tái)(大多數(shù))server 可用,整個(gè)系統(tǒng)保持可用。我們已經(jīng)了解到,一個(gè) zookeeper 集群如果要對(duì)外提供可用的服務(wù),那么集群中必須要有過(guò)半的機(jī)器正常工作并且彼此之間能夠正常通信,基于這個(gè)特性,如果向搭建一個(gè)能夠允許 F 臺(tái)機(jī)器down 掉的集群,那么就要部署 2*F+1 臺(tái)服務(wù)器構(gòu)成的zookeeper 集群。因此 3 臺(tái)機(jī)器構(gòu)成的 zookeeper 集群,能夠在掛掉一臺(tái)機(jī)器后依然正常工作。一個(gè) 5 臺(tái)機(jī)器集群的服務(wù),能夠?qū)?2 臺(tái)機(jī)器怪調(diào)的情況下進(jìn)行容災(zāi)。如果一臺(tái)由 6 臺(tái)服務(wù)構(gòu)成的集群,同樣只能掛掉 2 臺(tái)機(jī)器。因此,5 臺(tái)和 6 臺(tái)在容災(zāi)能力上并沒(méi)有明顯優(yōu)勢(shì),反而增加了網(wǎng)絡(luò)通信負(fù)擔(dān)。系統(tǒng)啟動(dòng)時(shí),集群中的 server 會(huì)選舉出一臺(tái)server 為 Leader,其它的就作為 follower(這里先不考慮observer 角色)。
之所以要滿足這樣一個(gè)等式,是因?yàn)?strong>一個(gè)節(jié)點(diǎn)要成為集群中的 leader,需要有超過(guò)及群眾過(guò)半數(shù)的節(jié)點(diǎn)支持,這個(gè)涉及到 leader 選舉算法。同時(shí)也涉及到事務(wù)請(qǐng)求的提交投票.

3.ZAB 協(xié)議

ZAB(Zookeeper Atomic Broadcast)原子廣播 協(xié)議是為分布式協(xié)調(diào)服務(wù) ZooKeeper 專門(mén)設(shè)計(jì)的一種\color{red}{支持崩潰恢復(fù)的原子廣播協(xié)議}
在 ZooKeeper 中,主要依賴 ZAB 協(xié)議來(lái)實(shí)現(xiàn)分布式數(shù)據(jù)一致性,基于該協(xié)議,ZooKeeper 實(shí)現(xiàn)了一種\color{red}{主備模式}的系統(tǒng)架構(gòu)來(lái)保持集群中各個(gè)副本之間的數(shù)據(jù)一致性.

zab 協(xié)議介紹 ZAB 協(xié)議包含兩種基本模式,分別是
    1. 崩潰恢復(fù)
    1. 原子廣播

當(dāng)整個(gè)集群啟動(dòng)時(shí),或者當(dāng) leader 節(jié)點(diǎn)出現(xiàn)網(wǎng)絡(luò)中斷、崩潰等情況時(shí),ZAB 協(xié)議就會(huì)進(jìn)入恢復(fù)模式選舉產(chǎn)生新的 Leader,當(dāng) leader 服務(wù)器選舉出來(lái)后,并且集群中過(guò)半的機(jī)器和該 leader 節(jié)點(diǎn)完成數(shù)據(jù)同步后(同步指的是數(shù)據(jù)同步,用來(lái)保證集群中過(guò)半的機(jī)器能夠和 leader 服務(wù)器的數(shù)據(jù)狀態(tài)保持一致),ZAB 協(xié)議就會(huì)退出恢復(fù)模式。當(dāng)集群中已經(jīng)有過(guò)半的 Follower 節(jié)點(diǎn)完成了和 Leader 狀態(tài)同步以后,那么整個(gè)集群就進(jìn)入了消息廣播模式。這個(gè)時(shí)候,在 Leader 節(jié)點(diǎn)正常工作時(shí),啟動(dòng)一臺(tái)新的服務(wù)器加入到集群,那這個(gè)服務(wù)器會(huì)直接進(jìn)入數(shù)據(jù)恢復(fù)模式,和leader 節(jié)點(diǎn)進(jìn)行數(shù)據(jù)同步。同步完成后即可正常對(duì)外提供非事務(wù)請(qǐng)求的處理。

崩潰恢復(fù)(數(shù)據(jù)恢復(fù))

ZAB 協(xié)議的這個(gè)基于原子廣播協(xié)議消息廣播過(guò)程,在正常情況下是沒(méi)有任何問(wèn)題的,但是一旦 Leader 節(jié)點(diǎn)崩潰,或者由于網(wǎng)絡(luò)問(wèn)題導(dǎo)致 Leader 服務(wù)器失去了過(guò)半的Follower 節(jié)點(diǎn)的聯(lián)系(leader 失去與過(guò)半 follower 節(jié)點(diǎn)聯(lián)系,可能是 leader 節(jié)點(diǎn)和 follower 節(jié)點(diǎn)之間產(chǎn)生了網(wǎng)絡(luò)分區(qū),那么此時(shí)的 leader 不再是合法的 leader 了),那么就會(huì)進(jìn)入到崩潰恢復(fù)模式。在ZAB 協(xié)議中,為了保證程序的正確運(yùn)行,整個(gè)恢復(fù)過(guò)程結(jié)束后需要選舉出一個(gè)新的Leader.

為了使 leader 掛了后系統(tǒng)能正常工作,需要解決以下兩個(gè)問(wèn)題
  • 1. 已經(jīng)被處理的消息不能丟失
    當(dāng) leader 收到合法數(shù)量 follower 的 ACKs 后,就向各個(gè) follower 廣播 COMMIT 命令,同時(shí)也會(huì)在本地執(zhí)行 COMMIT 并向連接的客戶端返回「成功」。但是如果在各個(gè) follower 在收到 COMMIT 命令前 leader 就掛了,導(dǎo)致剩下的部分服務(wù)器并沒(méi)有執(zhí)行都這條消息。
    leader 對(duì)事務(wù)消息發(fā)起 commit 操作,但是該消息在follower1 上執(zhí)行了,但是 follower2 還沒(méi)有收到 commit,就已經(jīng)掛了,而實(shí)際上客戶端已經(jīng)收到該事務(wù)消息處理成功的回執(zhí)了。所以在 zab 協(xié)議下需要保證所有機(jī)器都要執(zhí)行這個(gè)事務(wù)消息.
  • 2. 被丟棄的消息不能再次出現(xiàn)
    當(dāng) leader 接收到消息請(qǐng)求生成 proposal 還沒(méi)轉(zhuǎn)發(fā)到followe就掛了,其他 follower 并沒(méi)有收到此 proposal,因此經(jīng)過(guò)恢復(fù)模式重新選了 leader 后,這條消息是被跳過(guò)的。 此時(shí),之前掛了的 leader 重新啟動(dòng)并注冊(cè)成了 follower,他保留了被跳過(guò)消息的 proposal 狀態(tài),與整個(gè)系統(tǒng)的狀態(tài)是不一致的,需要將其刪除**。
消息廣播的實(shí)現(xiàn)原理

這個(gè)與分布式事務(wù)的 2pc 和 3pc 協(xié)議有關(guān),消息廣播的過(guò)程實(shí)際上是一個(gè)簡(jiǎn)化版本的二階段提交過(guò)程.

  1. leader 接收到事務(wù)型請(qǐng)求(增刪改)后,將消息賦予
    一個(gè)全局唯一64 位自增 id,叫:zxid,通過(guò) zxid 的大小
    比較既可以實(shí)現(xiàn)因果有序這個(gè)特征
  2. leader 為每個(gè) follower 準(zhǔn)備了一個(gè) FIFO 隊(duì)列(通過(guò) TCP
    協(xié)議來(lái)實(shí)現(xiàn),以實(shí)現(xiàn)了全局有序這一個(gè)特點(diǎn))將帶有 zxid
    的消息
    作為一個(gè)提案(proposal)分發(fā)給所有的 follower
  3. 當(dāng) follower 接收到 proposal,先把 proposal 寫(xiě)到磁盤(pán)
    寫(xiě)入成功以后再向 leader 回復(fù)一個(gè) ack
  4. 當(dāng) leader 接收到合法數(shù)量(超過(guò)半數(shù)節(jié)點(diǎn))的 ACK 后,
    leader 就會(huì)向這些 follower 發(fā)送 commit 命令,
    同時(shí)會(huì)
    在本地執(zhí)行該消息
  5. 當(dāng) follower 收到消息的 commit 命令以后,會(huì)提交該消

leader 的投票過(guò)程,不需要 Observer 的 ack,也就是Observer 不需要參與投票過(guò)程,但是 Observer 必須要同步 Leader 的數(shù)據(jù)從而在處理請(qǐng)求的時(shí)候保證數(shù)據(jù)的一致性

ZAB 協(xié)議需要滿足上面兩種情況,就必須要設(shè)計(jì)一個(gè)leader 選舉算法
能夠確保已經(jīng)被 leader 提交的事務(wù)Proposal能夠提交同時(shí)丟棄已經(jīng)被跳過(guò)的事務(wù)Proposal。
針對(duì)這個(gè)要求

  1. 如果 leader 選舉算法能夠保證新選舉出來(lái)的 Leader 服務(wù)器擁有集群中所有機(jī)器最高編號(hào)(ZXID 最大)的事務(wù)Proposal,那么就可以保證這個(gè)新選舉出來(lái)的 Leader 一定具有已經(jīng)提交的提案。

因?yàn)樗刑岚副?COMMIT 之前必須有超過(guò)半數(shù)的 follower ACK,即必須有超過(guò)半數(shù)節(jié)點(diǎn)的服務(wù)器的事務(wù)日志上有該提案的 proposal,因此,只要有合法數(shù)量的節(jié)點(diǎn)正常工作,就必然有一個(gè)節(jié)點(diǎn)保存了所有被 COMMIT 消息的 proposal 狀態(tài)另外一個(gè)
zxid 是 64 位
- 高 32 位是 epoch 編號(hào),每經(jīng)過(guò)一次 Leader 選舉產(chǎn)生一個(gè)新的 leader,新的 leader 會(huì)將epoch 號(hào)+1
- 低 32 位是消息計(jì)數(shù)器,每接收到一條消息這個(gè)值+1,新 leader 選舉后這個(gè)值重置為 0.

這樣設(shè)計(jì)的好處在于老的 leader 掛了以后重啟,它不會(huì)被選舉為 leader,因此此時(shí)它的 zxid 肯定小于當(dāng)前新的 leader。當(dāng)老的leader 作為 follower 接入新的 leader 后,新的leader 會(huì) 讓它將所有的擁有舊的 epoch 號(hào)的未被 COMMIT 的proposal 清除

關(guān)于 ZXID
zxid,也就是事務(wù) id
為了保證事務(wù)的順序一致性zookeeper 采用了遞增的事務(wù) id 號(hào)(zxid)來(lái)標(biāo)識(shí)事務(wù)。
所有的提議(proposal)都在被提出的時(shí)候加上了 zxid。
實(shí)際上 zxid 是一個(gè) 64 位的數(shù)字,它高 32 位是 epoch用來(lái)標(biāo)識(shí) leader 關(guān)系是否改變(ZAB 協(xié)議通過(guò) epoch 編號(hào)來(lái)區(qū)分 Leader 周期變化的策略),每次一個(gè) 新leader 被選出來(lái),它都會(huì)有一個(gè)新的epoch=(原來(lái)的 epoch+1),標(biāo)識(shí)當(dāng)前屬于那個(gè) leader 的統(tǒng)治時(shí)期。低 32 位用于遞增消息計(jì)數(shù).
epoch 的變化大家可以做一個(gè)簡(jiǎn)單的宕機(jī)實(shí)驗(yàn)

  1. 啟動(dòng)一個(gè) zookeeper 集群。
  2. 在 /tmp/zookeeper/VERSION-2 路 徑 下 會(huì) 看 到 一 個(gè)
    currentEpoch 文件。文件中顯示的是當(dāng)前的 epoch
  3. 把 leader 節(jié)點(diǎn)停機(jī),這個(gè)時(shí)候在看 currentEpoch 會(huì)有
    變化。 隨著每次選舉新的 leader,epoch 都會(huì)發(fā)生變化

4. leader 選舉

Leader 選舉會(huì)分兩個(gè)類型

  • 啟動(dòng)的時(shí)候的 leader 選舉
  • leader 崩潰的時(shí)候的的選舉
ZK服務(wù)器結(jié)點(diǎn)狀態(tài)分為四種
  • LOOKING (選舉狀態(tài),觀望狀態(tài))
  • LEADING
  • FOLLOWING
  • OBSERVING
服務(wù)器啟動(dòng)時(shí)的 leader 選舉

每個(gè)節(jié)點(diǎn)啟動(dòng)的時(shí)候狀態(tài)都是 LOOKING,處于觀望狀態(tài),接下來(lái)就開(kāi)始進(jìn)行選leader流程
進(jìn)行 Leader 選舉,至少需要兩臺(tái)機(jī)器
在集群初始化階段,當(dāng)有一臺(tái)服務(wù)器 Server1 啟動(dòng)時(shí),它本身是無(wú)法進(jìn)行和完成 Leader 選舉,當(dāng)?shù)诙_(tái)服務(wù)器 Server2 啟動(dòng)時(shí),這個(gè)時(shí)候兩臺(tái)機(jī)器可以相互通信,每臺(tái)機(jī)器都試圖找到 Leader,于是進(jìn)入 Leader 選舉過(guò)程。
選舉過(guò)程如下
(1) 每個(gè) Server 發(fā)出一個(gè)投票。由于是初始情況,Server1和 Server2 都會(huì)將自己作為 Leader 服務(wù)器來(lái)進(jìn)行投票,每次投票會(huì)包含所推舉的服務(wù)器的 myid 和 ZXID、epoch,使用(myid, ZXID,epoch)來(lái)表示,此時(shí) Server1的投票為(1, 0),Server2 的投票為(2, 0),然后各自將這個(gè)投票發(fā)給集群中其他機(jī)器。
(2) 接受來(lái)自各個(gè)服務(wù)器的投票。集群的每個(gè)服務(wù)器收到投票后,首先判斷該投票的有效性,如檢查是否是本輪投票(epoch)、是否來(lái)自LOOKING狀態(tài)的服務(wù)器。
(3) 處理投票。針對(duì)每一個(gè)投票,服務(wù)器都需要將別人的投票和自己的投票進(jìn)行 PK,
PK 規(guī)則如下
i. 優(yōu)先檢查 ZXID。ZXID 比較大的服務(wù)器優(yōu)先作為L(zhǎng)eader
ii. 如果 ZXID 相同,那么就比較 myid。myid 較大的服務(wù)器作為 Leader 服務(wù)器。對(duì)于 Server1 而言,它的投票是(1, 0),接收 Server2的投票為(2, 0),首先會(huì)比較兩者的 ZXID,均為 0,再比較 myid,此時(shí) Server2 的 myid 最大,于是更新自己的投票為(2, 0),然后重新投票,對(duì)于 Server2 而言,它不需要更新自己的投票,只是再次向集群中所有機(jī)器發(fā)出上一次投票信息即可。
(4) 統(tǒng)計(jì)投票。每次投票后,服務(wù)器都會(huì)統(tǒng)計(jì)投票信息,判斷是否已經(jīng)有過(guò)半機(jī)器接受到相同的投票信息,對(duì)于 Server1、Server2 而言,都統(tǒng)計(jì)出集群中已經(jīng)有兩
臺(tái)機(jī)器接受了(2, 0)的投票信息,此時(shí)便認(rèn)為已經(jīng)選出了 Leader。
(5) 改變服務(wù)器狀態(tài)。一旦確定了 Leader,每個(gè)服務(wù)器就會(huì)更新自己的狀態(tài),如果是 Follower,那么就變更為FOLLOWING,如果是 Leader,就變更為 LEADING。

運(yùn)行過(guò)程中的 leader 選舉

當(dāng)集群中的 leader 服務(wù)器出現(xiàn)宕機(jī)或者不可用的情況時(shí),那么整個(gè)集群將無(wú)法對(duì)外提供服務(wù),而是進(jìn)入新一輪的Leader 選舉,服務(wù)器運(yùn)行期間的 Leader 選舉和啟動(dòng)時(shí)期的 Leader 選舉基本過(guò)程是一致的。
(1) 變更狀態(tài)。Leader 掛后,余下的非 Observer 服務(wù)器都會(huì)將自己的服務(wù)器狀態(tài)變更為 LOOKING,然后開(kāi)始進(jìn)入 Leader 選舉過(guò)程。
(2) 每個(gè) Server 會(huì)發(fā)出一個(gè)投票。在運(yùn)行期間,每個(gè)服務(wù)器上的 ZXID 可能不同,此時(shí)假定 Server1 的 ZXID 為123,Server3的ZXID為122;在第一輪投票中,Server1和 Server3 都會(huì)投自己,產(chǎn)生投票(1, 123),(3, 122),然后各自將投票發(fā)送給集群中所有機(jī)器。接收來(lái)自各個(gè)服務(wù)器的投票。與啟動(dòng)時(shí)過(guò)程相同。
(3) 處理投票。與啟動(dòng)時(shí)過(guò)程相同,此時(shí),Server1 將會(huì)成
為 Leader。
(4) 統(tǒng)計(jì)投票。與啟動(dòng)時(shí)過(guò)程相同。
(5) 改變服務(wù)器的狀態(tài)。與啟動(dòng)時(shí)過(guò)程相同

Leader 選舉源碼分析





啟動(dòng)主線程,QuorumPeer 重寫(xiě)了 Thread.start 方法調(diào)用

調(diào)用QUORUMPEER的START方法

loaddatabase 主要是從本地文件中恢復(fù)數(shù)據(jù),以及獲取最新的 zxid

初始化LEADERELECTION


配置選舉算法,選舉算法有3 種,可以通過(guò)在 zo o.cfg 里面進(jìn)行配置,默認(rèn)是 fast 選舉

繼續(xù)看FastLeaderElection 的初始化動(dòng)作,主要初始化了業(yè)務(wù)層的發(fā)送隊(duì)列和接收隊(duì)列


接下來(lái)調(diào)用fle.start() , 也就是會(huì)調(diào)用 FastLeaderElectionstart() 方法,該方法主要是對(duì)發(fā)送線程和接收線程的初始化 ,左邊是 FastLeaderElection 的 start ,右邊是messager .start()

wsThread 和 wrThread 的初始化動(dòng)作在FastLeaderElection的 starter 方法里面進(jìn)行,這里面有兩個(gè)內(nèi)部類,一個(gè)是 WorkerSender ,一個(gè)是 WorkerReceiver負(fù)責(zé)發(fā)送投票信息和接收投票信息

然后再回到QuorumPeer .java 。 FastLeaderElection 初始化完成以后,調(diào)用 super . start(),最終運(yùn)行 QuorumPeer 的run 方法

前面部分主要是做JMX 監(jiān)控注冊(cè)

重要的代碼在這個(gè)while 循環(huán)里

調(diào)用setCurrentVote(makeLEStrategy(). lookForLeader());最終根據(jù)策略應(yīng)該運(yùn)行 Fast LeaderElection 中的選舉算法

LOOKFORLEADER開(kāi)始選舉











消息如何廣播,看SENDNOTIFICATIONS



WORKERSENDER


FastLeaderElection 選舉過(guò)程

其實(shí)在這個(gè)投票過(guò)程中就涉及到幾個(gè)類
FastLeaderElection: FastLeaderElection 實(shí)現(xiàn)了 Election 接口 ,實(shí)現(xiàn) 各服務(wù)器之間基于 TCP 協(xié)議進(jìn)行選舉
Notification:內(nèi)部類, Notification 表示收到的選舉投票信息(其他服務(wù)器發(fā)來(lái)的選舉投票信息),其包含了被選舉者的 id 、 zxid 、選舉周期等信息
ToSend: ToSend 表示發(fā)送給其他服務(wù)器的選舉投票信息,也包含了被選舉者的
id 、 zxid 、選舉周期等信息
Messenger: Messenger 包含了 WorkerReceiver 和WorkerSender 兩個(gè)內(nèi)部類

  • WorkerReceiver實(shí)現(xiàn)了 Runnable 接口,是選票接收器。其會(huì)不斷地從 QuorumCnxManager 中獲取其他服務(wù)器發(fā)來(lái)的選舉消息,并將其轉(zhuǎn)換成一個(gè)選票,然后保存到recvqueue 中
  • WorkerSender也實(shí)現(xiàn)了 Runnable 接口,為選票發(fā)送器,其會(huì)不斷地從 sendqueue 中獲取待發(fā)送的選票,并將其傳遞到底層 QuorumCnxManager 中
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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