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事件处理

监测到主节点离线后回重新监测法定节点数,并进行新一轮的选择;

I am chris, and what about you?
原文地址:https://www.cnblogs.com/arax/p/14426285.html