久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

zookeeper選舉的源碼過程是什么樣的

173次閱讀
沒有評論

共計 4384 個字符,預(yù)計需要花費 11 分鐘才能閱讀完成。

zookeeper 選舉的源碼過程是什么樣的,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面丸趣 TV 小編將為大家詳細(xì)講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。

集群概述

zookeper 在生產(chǎn)環(huán)境中通常都是通過集群方式來部署的,以保證高可用, 下面是 zookeeper 官網(wǎng)給出的一個集群部署結(jié)構(gòu)圖:

從上圖可以得出,zookeeper  server 的每個節(jié)點都和主節(jié)點保持通訊的,每個節(jié)點上面都存儲有數(shù)據(jù)和日志的備份,只有當(dāng)大多數(shù)節(jié)點可用集群才是可用的。本文主要是基于 zookeeper  3.8.0 講解,主要是通過源碼的維度來分析 zookeeper 選舉過程 對于 zookeeper 的源碼編譯大家可以參考:編譯運行 Zookeeper 源碼

集群節(jié)點狀態(tài)

集群節(jié)點狀態(tài)定義在 QuorumPeer#ServerState 枚舉,主要是包含 LOOKING、FOLLOWING、LEADING、OBSERVING   四個狀態(tài), 下面是定義的代碼和說明

public enum ServerState { //  尋找 leader 狀態(tài)。當(dāng)服務(wù)器處于該狀態(tài)時,它會認(rèn)為當(dāng) -  前集群中沒有 leader,因此需要進入 leader 選舉狀態(tài)。 LOOKING, //  跟隨者狀態(tài)。表明當(dāng)前服務(wù)器角色是  follower。 FOLLOWING, //  領(lǐng)導(dǎo)者狀態(tài)。表明當(dāng)前服務(wù)器角色是  leader。 LEADING, //  觀察者狀態(tài)。表明當(dāng)前服務(wù)器角色是  observer。 OBSERVING }

Leader 選舉過程啟動和初始化

QuorumPeerMain 是 zookeeper 的啟動類,通過 main 方法啟動

//  不展示非核心代碼  public static void main(String[] args) { QuorumPeerMain main = new QuorumPeerMain(); main.initializeAndRun(args); } protected void initializeAndRun(String[] args) throws ConfigException, IOException, AdminServerException { //  集群模式啟動  if (args.length == 1   config.isDistributed()) { runFromConfig(config); } else { } } public void runFromConfig(QuorumPeerConfig config) throws IOException, AdminServerException { // quorumPeer  啟動  quorumPeer.start(); }

QuorumPeer 是一個線程實例類,當(dāng)調(diào)用 start 方法過后會致性 QuorumPeer#run() 方法,  進行集群狀態(tài)的判斷最終進入是否執(zhí)行選舉或者同步集群節(jié)點數(shù)據(jù)信息等一系列的操作,下面是核心代碼:

@Override public void run() { try { while (running) { switch (getPeerState()) { case LOOKING: //  投票給自己  setCurrentVote(makeLEStrategy().lookForLeader()); break; case OBSERVING: setObserver(makeObserver(logFactory)); observer.observeLeader(); break; case FOLLOWING: setFollower(makeFollower(logFactory)); follower.followLeader(); break; case LEADING: setLeader(makeLeader(logFactory)); leader.lead(); setLeader(null); break; } } } finally { } }

進行選舉

FastLeaderElection 是選舉的核心類,在這個類里面有對投票和選票的處理過程

public Vote lookForLeader() throws InterruptedException { //  創(chuàng)建一個當(dāng)前選舉周期的投票箱  Map Long, Vote  recvset = new HashMap Long, Vote  //  創(chuàng)建一個投票箱。這個投票箱和 recvset  不一樣。 //  存儲當(dāng)前集群中如果已經(jīng)存在 Leader 了的投票  Map Long, Vote  outofelection = new HashMap Long, Vote  int notTimeout = minNotificationInterval; synchronized (this) { //  遞增本地選舉周期  logicalclock.incrementAndGet(); //  為自己投票  updateProposal(getInitId(), getInitLastLoggedZxid(), getPeerEpoch()); } //  廣播投票  sendNotifications(); SyncedLearnerTracker voteSet = null; //  如果當(dāng)前服務(wù)器的狀態(tài)為 Looking,和 stop 參數(shù)為 false,那么進行選舉  while ((self.getPeerState() == ServerState.LOOKING)   (!stop)) { if (n.electionEpoch   logicalclock.get()) { logicalclock.set(n.electionEpoch); recvset.clear(); // totalOrderPredicate  投票  PK if (totalOrderPredicate(n.leader, n.zxid, n.peerEpoch, getInitId(), getInitLastLoggedZxid(), getPeerEpoch())) { updateProposal(n.leader, n.zxid, n.peerEpoch); } else { updateProposal(getInitId(), getInitLastLoggedZxid(), getPeerEpoch()); } sendNotifications(); } else if (totalOrderPredicate(n.leader, n.zxid, n.peerEpoch, proposedLeader, proposedZxid, proposedEpoch)) { updateProposal(n.leader, n.zxid, n.peerEpoch); sendNotifications(); } //  監(jiān)聽通信層接收的投票  Notification n = recvqueue.poll(notTimeout, TimeUnit.MILLISECONDS); //  放入投票箱  recvset.put(n.sid, new Vote(n.leader, n.zxid, n.electionEpoch, n.peerEpoch)); //  過半邏輯  voteSet = getVoteTracker(recvset, new Vote(proposedLeader, proposedZxid, logicalclock.get(), proposedEpoch)); } }

totalOrderPredicate 主要是選票 PK 的邏輯,我們再來看看代碼:

protected boolean totalOrderPredicate(long newId, long newZxid, long newEpoch, long curId, long curZxid, long curEpoch) { if (self.getQuorumVerifier().getWeight(newId) == 0) { return false; } return ((newEpoch   curEpoch) || ((newEpoch == curEpoch)   ((newZxid   curZxid) || ((newZxid == curZxid)   (newId   curId))))); }

選舉過程是這個樣子的,其實官方也給出了注釋:

鴻蒙官方戰(zhàn)略合作共建——HarmonyOS 技術(shù)社區(qū)

先比較選舉的屆數(shù),屆數(shù)高的說明是最新一屆,勝出

再比較 zxid,也就是看誰的數(shù)據(jù)最新,最新的勝出

最后比較 serverid,這是配置文件指定的,節(jié)點 id 大者勝出 選舉完成后通過 sendNotifications(); 通知其他的節(jié)點。

過程總結(jié)

前面我粗略的講解 zookeeper 從啟動過程在到選舉,選舉結(jié)果同步的,以及如何進行投票的選舉結(jié)果確認(rèn)過程,但是 zookeeper   作為一個高性能、高可靠的分布式協(xié)調(diào)中間件,在很多設(shè)計的細(xì)節(jié)也是非常的優(yōu)秀的。

投票過程

通常情況下,在投票的過程中 zxid 越大越有可能成為 leader 主要是由于 zxid   越大該節(jié)點的數(shù)據(jù)越多,這樣的話就可以減少數(shù)據(jù)的同步過程中節(jié)點事務(wù)的撤銷和日志文件同步的比較過程,以提升性能。下面是 5 個 zookeeper 節(jié)點選舉的過程。

注: (sid, zxid), 當(dāng)前場景為  server1 ,server2 出現(xiàn)故障,server3 的 zxid = 9,server4 和 server5 的 zxid 為 8.   進行兩輪選舉,最終選出 sever3 為 leader 節(jié)點

多層網(wǎng)絡(luò)架構(gòu)

在前面的分析過程中我省略了 Zookeeper 節(jié)點之間通訊的 NIO 操作,這部分簡單來講 zookeeper 將他們劃分為傳輸層和業(yè)務(wù)層。通過  SendWorker、RecvWorker 處理網(wǎng)絡(luò)層數(shù)據(jù)包,WorkerSender 和 WorkerReceiver 處理業(yè)務(wù)層的數(shù)據(jù)。

這里會涉及到多線程操作,zookeeper   在源碼中也給出了大量的日志信息,對于初學(xué)者有一定的難度,對此大家可以參考下面的 Zookeeper 選舉源碼流程 這部分的流程圖來輔助分析。

Leader 選舉源碼流程

結(jié)合上面的梳理,我對 zookeeper 啟動和選舉的流程做了一個比較詳細(xì)的梳理。

看完上述內(nèi)容是否對您有幫助呢?如果還想對相關(guān)知識有進一步的了解或閱讀更多相關(guān)文章,請關(guān)注丸趣 TV 行業(yè)資訊頻道,感謝您對丸趣 TV 的支持。

正文完
 
丸趣
版權(quán)聲明:本站原創(chuàng)文章,由 丸趣 2023-08-25發(fā)表,共計4384字。
轉(zhuǎn)載說明:除特殊說明外本站除技術(shù)相關(guān)以外文章皆由網(wǎng)絡(luò)搜集發(fā)布,轉(zhuǎn)載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 奈曼旗| 垣曲县| 水富县| 仙桃市| 喀喇| 青铜峡市| 时尚| 博乐市| 邵东县| 安仁县| 裕民县| 潮安县| 和龙市| 岢岚县| 辉县市| 宜阳县| 登封市| 兴城市| 九龙县| 嘉鱼县| 桃园县| 贡觉县| 盐池县| 江达县| 保山市| 台州市| 郸城县| 茶陵县| 牙克石市| 城口县| 桂东县| 太原市| 前郭尔| 青神县| 简阳市| 唐海县| 平利县| 遂川县| 洛宁县| 花莲市| 株洲市|