ES中的選舉機制


一、概述

  • 在Elasticsearch當中,ES分為四種角色:master、data(數據節點)、Coordinating(協調節點)、Ingest(預處理節點)。
  • master、data、Coordinating三種角色由elasticsearch.yml配置文件中的node.master、node.data來控制;Ingest角色有node.ingest來控制
  • 如果不修改elasticsearch的節點角色信息,那么默認就是node.master: true、node.data: true、node.ingest: true。
  • 默認情況下,一個節點可以充當一個或多個角色,默認四個角色都有。都有成為主節點的資格,也都存儲數據,還可以提供查詢服務,負載均衡以及數據合並等服務。在高並發的場景下集群容易出現負載過高問題。

二、角色划分

1. master:

  • master節點具備主節點的選舉權,有資格成為主節點,主節點控制整個集群的元數據(metadata),比如索引的新增、刪除、分片分配等;
  • 該節點不和應用創建連接,master節點不占用IO和CPU,內存使用量一般;
  • 角色配置方式:node.master: true

2. data:

  • 該節點和應用創建連接、接收索引請求,會存儲分配在該node上的shard的數據並負責這些shard的寫入、查詢等,ES集群的性能取決於該節點的個數(每個節點最優配置的情況下),data節點會占用大量的CPU、io和內存;
  • data節點的分片執行查詢語句、獲得查詢結果后將結果反饋給Coordinating,此過程較消耗硬件資源;
  • 角色配置方式:node.data: true

3. Coordinating:

  • 該節點和檢索應用創建連接、接受檢索請求,但其本身不負責存儲數據,可當負責均衡節點,Coordinating節點不占用io、cpu和內存;
  • Coordinating節點接受搜索請求后將請求轉發到與查詢條件相關的多個data節點的分片上,然后多個data節點的分片執行查詢語句或者查詢結果再返回給Coordinating節點,Coordinating來把各個data節點的返回結果進行整合、排序等一系列操作后再將最終結果返回給用戶請求。
  • 角色配置方式:node.master: false,node.data: false

4. Ingest Node節點:

  • 可以在任何節點上啟用 ingest,甚至使用專門的 ingest nodes
  • Ingest node 專門對索引的文檔做預處理,發生在對真實文檔建立索引之前。在建立索引對文檔預處理之前,先定義一個管道(pipeline),管道里指定了一系列的處理器。每個處理器能夠把文檔按照某種特定的方式轉換。比如在管道里定義一個從某個文檔中移除字段的處理器,緊接着一個重命名字段的處理器。集群的狀態也會被存儲到配置的管道內。定義一個管道,簡單的在索引或者bulk request(一種批量請求方法)操作上定義 pipeline 參數,這樣 ingest node 就會知道哪個管道在使用。這個節點在使用過程中用的也不多,所以大概了解一下就行;
  • 角色配置方式:node.ingest: true

 

三、節點發現

ZenDiscovery是ES自己實現的一套用於節點發現和選主等功能的模塊,沒有依賴Zookeeper等工具,官方文檔

簡單來說,節點發現依賴以下配置:

conf/elasticsearch.yml:
    discovery.zen.ping.unicast.hosts: [1.1.1.1, 1.1.1.2, 1.1.1.3]

這個配置可以看作是,在本節點到每個hosts中的節點建立一條邊,當整個集群所有的node形成一個聯通圖時,所有節點都可以知道集群中有哪些節點,不會形成孤島。

官方推薦這里設置為所有的master-eligible node。

四、master節點選舉

上面提到,集群中可能會有多個master-eligible node,此時就要進行master選舉,保證只有一個當選master。如果有多個node當選為master,則集群會出現腦裂,腦裂會破壞數據的一致性,導致集群行為不可控,產生各種非預期的影響。

為了避免產生腦裂,ES采用了常見的分布式系統思路,保證選舉出的master被多數派(quorum)的master-eligible node認可,以此來保證只有一個master。這個quorum通過以下配置進行配置:

conf/elasticsearch.yml:
    discovery.zen.minimum_master_nodes: 2

這個配置對於整個集群非常重要。

1. master選舉誰發起,什么時候發起?

master選舉當然是由master-eligible節點發起,當一個master-eligible節點發現滿足以下條件時發起選舉:

  1. 該master-eligible節點的當前狀態不是master。
  2. 該master-eligible節點通過ZenDiscovery模塊的ping操作詢問其已知的集群其他節點,沒有任何節點連接到master。
  3. 包括本節點在內,當前已有超過minimum_master_nodes個節點沒有連接到master。

總結一句話,即當一個節點發現包括自己在內的多數派的master-eligible節點認為集群沒有master時,就可以發起master選舉。

 

2. 當需要選舉master時,選舉誰?

首先是選舉誰的問題,如下面源碼所示,選舉的是排序后的第一個MasterCandidate(即master-eligible node)。

public MasterCandidate electMaster(Collection<MasterCandidate> candidates) {
        assert hasEnoughCandidates(candidates);
        List<MasterCandidate> sortedCandidates = new ArrayList<>(candidates);
        sortedCandidates.sort(MasterCandidate::compare);
        return sortedCandidates.get(0);
}

 

那么是按照什么排序的?

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;
}

 

如上面源碼所示,先根據節點的clusterStateVersion比較,clusterStateVersion越大,優先級越高。clusterStateVersion相同時,進入compareNodes,其內部按照節點的Id比較(Id為節點第一次啟動時隨機生成)。

總結一下:

  1. 當clusterStateVersion越大,優先級越高。這是為了保證新Master擁有最新的clusterState(即集群的meta),避免已經commit的meta變更丟失。因為Master當選后,就會以這個版本的clusterState為基礎進行更新。(一個例外是集群全部重啟,所有節點都沒有meta,需要先選出一個master,然后master再通過持久化的數據進行meta恢復,再進行meta同步)。
  2. 當clusterStateVersion相同時,節點的Id越小,優先級越高。即總是傾向於選擇Id小的Node,這個Id是節點第一次啟動時生成的一個隨機字符串。之所以這么設計,應該是為了讓選舉結果盡可能穩定,不要出現都想當master而選不出來的情況。
3. 什么時候選舉成功?

當一個master-eligible node(我們假設為Node_A)發起一次選舉時,它會按照上述排序策略選出一個它認為的master。

  • 假設Node_A選Node_B當Master,Node_A會向Node_B發送join請求,那么此時:

    (1) 如果Node_B已經成為Master,Node_B就會把Node_A加入到集群中,然后發布最新的cluster_state, 最新的cluster_state就會包含Node_A的信息。相當於一次正常情況的新節點加入。對於Node_A,等新的cluster_state發布到Node_A的時候,Node_A也就完成join了。

    (2) 如果Node_B在競選Master,那么Node_B會把這次join當作一張選票。對於這種情況,Node_A會等待一段時間,看Node_B是否能成為真正的Master,直到超時或者有別的Master選成功。

    (3) 如果Node_B認為自己不是Master(現在不是,將來也選不上),那么Node_B會拒絕這次join。對於這種情況,Node_A會開啟下一輪選舉。

  • 假設Node_A選自己當Master:

    此時NodeA會等別的node來join,即等待別的node的選票,當收集到超過半數的選票時,認為自己成為master,然后變更cluster_state中的master node為自己,並向集群發布這一消息。

4. 節點失效監測

這里的錯誤檢測可以理解為類似心跳的機制,有兩類錯誤檢測:

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

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

NodesFaultDetection事件處理:

  如果Master檢測到某個Node連不上了,會執行removeNode的操作,將節點從cluste_state中移除,並發布新的cluster_state。當各個模塊apply新的cluster_state時,就會執行一些恢復操作,比如選擇新的primaryShard或者replica,執行數據復制等。

MasterFaultDetection事件處理:

  如果某個Node發現Master連不上了,會清空pending在內存中還未commit的new cluster_state,然后發起rejoin,重新加入集群。(如果達到選舉條件則觸發新master選舉)

五、主分片和副本分片機制

我們知道es中保存數據的時候是有主分片和副本分片的,那么副本分片的作用有哪些呢?

  1. 作為備份,防止主分片崩潰
  2. 分擔查詢請求,請求會在主分片和副本分片之間均勻分布


主副本之前角色的切換如何發生的?
當主分片不可用時,es就會重新進行選舉,把最新的副本分片提高到主分片的地位,這里es的master節點實現了主副本選舉的邏輯

參考鏈接:

https://blog.csdn.net/qq_35373760/article/details/108974308


免責聲明!

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



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