91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

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

發布時間:2021-11-01 09:51:02 來源:億速云 閱讀:160 作者:柒染 欄目:系統運維

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

集群概述

zookeper 在生產環境中通常都是通過集群方式來部署的,以保證高可用, 下面是 zookeeper 官網給出的一個集群部署結構圖:

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

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

集群節點狀態

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

public enum ServerState {     // 尋找leader狀態。當服務器處于該狀態時,它會認為當- 前集群中沒有leader,因此需要進入leader選舉狀態。     LOOKING,     // 跟隨者狀態。表明當前服務器角色是 follower。     FOLLOWING,       // 領導者狀態。表明當前服務器角色是 leader。     LEADING,     // 觀察者狀態。表明當前服務器角色是 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 是一個線程實例類,當調用 start 方法過后會致性 QuorumPeer#run() 方法,  進行集群狀態的判斷最終進入是否執行選舉或者同步集群節點數據信息等一系列的操作,下面是核心代碼:

@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 {     // 創建一個當前選舉周期的投票箱     Map<Long, Vote> recvset = new HashMap<Long, Vote>();     // 創建一個投票箱。這個投票箱和recvset 不一樣。     // 存儲當前集群中如果已經存在Leader了的投票     Map<Long, Vote> outofelection = new HashMap<Long, Vote>();     int notTimeout = minNotificationInterval;     synchronized (this) {         // 遞增本地選舉周期         logicalclock.incrementAndGet();         // 為自己投票         updateProposal(getInitId(), getInitLastLoggedZxid(), getPeerEpoch());     }     // 廣播投票     sendNotifications();     SyncedLearnerTracker voteSet = null;     // 如果當前服務器的狀態為Looking,和stop參數為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();         }         // 監聽通信層接收的投票         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))))); }

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

  1. 鴻蒙官方戰略合作共建——HarmonyOS技術社區

  2. 先比較選舉的屆數,屆數高的說明是最新一屆,勝出

  3. 再比較zxid,也就是看誰的數據最新,最新的勝出

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

過程總結

前面我粗略的講解 zookeeper 從啟動過程在到選舉,選舉結果同步的,以及如何進行投票的選舉結果確認過程,但是 zookeeper  作為一個高性能、高可靠的分布式協調中間件,在很多設計的細節也是非常的優秀的。

投票過程

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

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

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

多層網絡架構

在前面的分析過程中我省略了 Zookeeper 節點之間通訊的 NIO 操作, 這部分簡單來講 zookeeper 將他們劃分為傳輸層和業務層。通過  SendWorker、RecvWorker 處理網絡層數據包, WorkerSender 和 WorkerReceiver 處理業務層的數據。

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

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

Leader 選舉源碼流程

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

看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

桦甸市| 潢川县| 永泰县| 南雄市| 石渠县| 武功县| 博罗县| 东至县| 金塔县| 咸宁市| 铜川市| 禹州市| 湘西| 五指山市| 泸溪县| 长白| 巨野县| 清原| 凉山| 赣榆县| 青阳县| 铁力市| 晋江市| 淄博市| 青海省| 涞源县| 延庆县| 汉川市| 太仆寺旗| 乌兰浩特市| 陵川县| 民和| 玛沁县| 阳春市| 元氏县| 津市市| 东平县| 临汾市| 盐亭县| 辛集市| 江都市|