zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    Linux基础命令grep(如何过滤字符串)
    Linux基础命令wc(如何统计文件的行数?如何统计文件的字节数?)
    Linux基础命令tr(如何替换字符)
    django4
    django3
    django2
    django1
    jQuery2
    jQuery1
    事件
  • 原文地址:https://www.cnblogs.com/wslook/p/14701318.html
Copyright © 2011-2022 走看看