ES 選舉Master節點機制


ES采用主從模式架構,Master節點的選取對整個集群的可用性及數據一致性都起到了關鍵作用,下面介紹一下ES選取主節點的流程(版本6.1)

整體流程

選舉臨時Master節點,判斷如果本節當選,則等待選票超過半數,成為真正的Master節點,如果本節點不是臨時Master節點,則嘗試加入集群,加入集群其實是投票的過程,整體流程如下:

1 選取臨時節點

1.1 ping所有節點,獲取節點列表fullPingResponses,並將自己添加到列表中

1.2 構建目前存在的master列表activeMasters

獲取請求結果的所有節點的master節點

List<DiscoveryNode> activeMasters = new ArrayList<>();
for (ZenPing.PingResponse pingResponse : pingResponses) {
    // We can't include the local node in pingMasters list, otherwise we may up electing ourselves without
    // any check / verifications from other nodes in ZenDiscover#innerJoinCluster()
    if (pingResponse.master() != null && !localNode.equals(pingResponse.master())) {
        activeMasters.add(pingResponse.master());
    }
}

1.3構建master候選列表masterCandidates

將ping獲取的列表中,在啟動時node.master true 的篩選出來,作為候選master

List<ElectMasterService.MasterCandidate> masterCandidates = new ArrayList<>();
for (ZenPing.PingResponse pingResponse : pingResponses) {
    if (pingResponse.node().isMasterNode()) {
        masterCandidates.add(new ElectMasterService.MasterCandidate(pingResponse.node(), pingResponse.getClusterStateVersion()));
    }
}

2 選擇出臨時master

整體流程如下:

  • 判斷activeMasters是否為空,如果不為空從activeMasters中選取一個節點作為臨時主節點;
public DiscoveryNode tieBreakActiveMasters(Collection<DiscoveryNode> activeMasters) {
    return activeMasters.stream().min(ElectMasterService::compareNodes).get();
}

直接使用選取排序后最小的作為臨時master,比較器的規則:

/** master nodes go before other nodes, with a secondary sort by id **/
    private static int compareNodes(DiscoveryNode o1, DiscoveryNode o2) {
    if (o1.isMasterNode() && !o2.isMasterNode()) {
        return -1;
    }
    if (!o1.isMasterNode() && o2.isMasterNode()) {
        return 1;
    }
    // 直接使用node的id進行比較
    return o1.getId().compareTo(o2.getId());
}
  • 如果activeMasters為空,則從候選列表masterCandidates中選取一個作為臨時主節點;

masterCandidates中選取主節點時,首先需要判斷候選人數是否達到了半數以上,當滿足半數以上時,開始選擇主節點,選擇主節點的規則比較簡單:

public static int compare(MasterCandidate c1, MasterCandidate c2) {
    // we explicitly swap c1 and c2 here. the code expects "better" is lower in a sorted
    // list, so if c2 has a higher cluster state version, it needs to come first.
    int ret = Long.compare(c2.clusterStateVersion, c1.clusterStateVersion);
    if (ret == 0) {
        ret = compareNodes(c1.getNode(), c2.getNode());
    }
    return ret;
}

先比較集群狀態的版本,選擇集群狀態版本較高的作為臨時master,如果相同,則按照和activeMasters中選取的方式一樣取ID較小的作為臨時Master;

確立Master或者加入集群

  • 如果本節點被選為臨時Master,等待(默認30s)足夠多節點加入本節點(超過一半)后,完成選舉,並發布新的clusterState
  • 如果其他節點本選為臨時Master節點,向Master節點發送加入集群的請求,等待(1分鍾)回復,最終master會發布集群狀態,並確認客戶join請求;

如果以上處理失敗,則重新開始新一輪的選舉;

節點失效監測

  • Master節點啟動NodesFaultDetection定期監測加入集群的節點是否活躍;
  • 非Master節點啟動MasterFaultDetection定期監測Master節點是否活躍;

節點監測都是通過定期(1s)發送ping探測節點是否正常,如果超過3次,則開始處理節點離開事件;

NodesFaultDetection事件處理

檢查集群是否達到了法定節點數(過半),如果不足,則放棄Master重新加入集群,這樣做的目的是為了防止產生雙主,例如集群中有5個節點[A,B,C,D,E],A為主節點,由於某種原因,集群網絡出現分區[A,B],[C,D,E],這時候[C,D,E] 組成的分區監測不到主節點開始處理MasterFaultDetection重新選舉主節點,假設選舉C為主節點;由於A節點無法監測到[C,D,E]三個節點,開始處理NodesFaultDetection,這時候如果A所在分區如果不監測法定節點數,繼續作為主節點;整個集群會出現兩個主節點A,C;

MasterFaultDetection事件處理

監測到主節點離線后回重新監測法定節點數,並進行新一輪的選擇;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM