Elasticsearch源码解析(三)——选主流程

Elasticsearch通过Discovery模块来发现集群节点以及选举主节点,具体的实现为ZenDiscovery。

1 ES的选举算法

1.1 Bully算法

假定集群的所有节点都有一个唯一ID,对这些节点ID排序,任何时候Leader都是ID最大或最小的节点。
优点:简单易实现。
缺点:当最大(小)ID的节点不稳定时,可能会有问题。比如最大节点ID为5,当5掉线时,4号被选为主节点,如果5号恢复,5号又被再次选为新主,如果5号节点不稳定,会导致主节点频繁切换。

1.2 ES的改进

ES通过推迟选举,直到当前的Master失效来解决上述问题。只要当前Master不挂掉,就不会重新选主。比如4号节点当选Master,只要4号不挂掉,就不会再选择5号节点。
缺点:容易产生脑裂(双主),需通过“半数以上”机制解决脑裂问题。

2 相关配置

以下是和选主相关的几个参数(非全部):

// 组成集群需要的最少master资格节点数,默认-1
discovery.zen.minimum_master_nodes
// ping超时时间,默认3秒
discovery.zen.ping_timeout
// 节点加入现有集群的超时时间,默认ping_timeout的20倍
discovery.zen.join_timeout

其中最重要的是discovery.zen.minimum_master_nodes,为了避免脑裂,应该设置成m/2+1,m为有master资格的节点数。
现在这个配置已经不仅仅是字面意思,还决定了下面几个点:

  1. 触发选举:当需要有几台master资格的节点上线时才开始选举
  2. 决定Master:临时master转为正式master的得票数
  3. gateway元信息选举:向有master资格的节点发起请求,通过的响应数
  4. 集群状态发布:发布成功的响应数

3 流程概述

  1. 通过节点ID,选举临时Master
  2. 投票与得票(join请求)
  3. 判断本节点当选与否。本节点当选则等待确认,否则尝试加入到当选的master所在的集群
  4. 启动节点失效探测器,以对节点的离线事件作出相应

负责选主流程的线程池:generic线程池(ES实例化了很多个线程池来完成不同类型的任务,generic是其中一个)
所有节点(包括非master资格的)都会参选并投票
选举胜利条件:票数达到 discovery.zen.minimum_master_nodes

3.1 选举临时Master

程序入口:ZenDiscovery#findMaster
一句话概述:查找当前集群活跃的Master(activeMasters) 或者 从候选节点(masterCandidates)中选择新的Master。
具体过程:

  1. ping所有节点,获取fullPingResponses列表。
  2. 构建两个列表:activeMasters列表 和 masterCandidates列表。
// 如果设置了以下参数,在第二步会忽略无master资格的节点的信息
discovery.zen.master_election.ignore_non_master_pings=true
3.1.1 fullPingResponses列表

首先,ping所有节点,获取fullPingResponses列表,ping过程不包括自己,自己是单独添加。
在这里插入图片描述

3.1.2 activeMasters列表

构建activeMasters列表,这个过程主要是将集群当前已存在的master加入到activeMaster列表,正常情况下只会有一个。
构建activeMasters列表

3.1.3 MasterCandidates列表

构建masterCandidates列表,比较简单,遍历fullPingResponses,只要是来自master资格的节点,都加入。
所以masterCandidates保存的是当前所有有master资格的节点。

3.1.4 整体流程:

综上所述,主要就是三个列表:fullPingResponses、activeMaster、MasterCandidates。
如果activeMaster为空,那么就从masterCandidates中选主(这个时候一般是集群刚启动)。
如果activeMaster非空,那么就送activeMaster中选主(这个时候一般是新节点加入,比如加一台机器)。
整体流程

3.1.5 从masterCandidates中选主

相关类:org.elasticsearch.discovery.zen.ElectMasterService
从masterCandidates中选主时,首先要判断是否达到过半条件,否则选主失败:
在这里插入图片描述
如果达到过半条件,从候选中选一个出来做Master:
在这里插入图片描述
可以看到结果是get(0),再看看比较函数:
在这里插入图片描述
可以看到,会优先返回集群状态版本更大的节点。再继续:
在这里插入图片描述
之后再优先返回master资格的节点,最后返回节点ID最小的。
masterCandidates中的一定都是有master资格的,这里任然加两个if,原因是compareNodes可能在别处被调用。
总结,从masterCandidates中选主优先级:

  1. 集群状态最新的。
  2. 有master资格的。
  3. 节点ID最小的。
3.1.6 从activeMasters中选主

很简单,任然依赖compareNodes()来排序,取get(0)
在这里插入图片描述

3.2 投票与得票

至此,临时Master已经选举完成,接下来需要通过得票数来判断是否能转正。

投票,就是发送加入集群的请求joinRequest。
得票,就是joinRequest的请求数。
投票统计入口:ZenDiscovery#handleJoinRequest
最终会调用到下面的方法,可以看到会忽略非master资格的节点的投票:
在这里插入图片描述

3.3 确定Master或者加入集群

上述选出的临时Master有两种情况:要么是本节点,要么不是。
如果是本节点:
1.等待足够多的票数(join请求)才能胜选。
2.如果超时时间内(默认30s),还没有足够的票数,则选举失败,重新开始选举过程。
3.发布集群状态clusterState,再响应join请求。

不是本节点:
1.不再接受join请求
2.加入被选的Master(发送join请求)
3.当选的master先发布集群状态,再响应所有join请求。

只要确认了正式Master,都是先发布集群状态,再响应join请求。
所以对于那些没有当选的节点,join请求返回时,已经持有了集群状态了。

3.4 节点失效检测

主节点和数据节点都有可能掉线,所以有两种失效检测探测:

  1. 从Master角度,检测非Master是否离线,启动NodesFaultDetection,NodesFD。
  2. 从非Master角度,检测Master是否离线,启动MasterFaultDetection,MasterFD。

原理都是定时发送ping请求,失败一定次数时判定节点离线。

3.4.1 NodesFaultDetection

首先检查一下剩下的节点数是否仍然过半,否则放弃Master身份,重新加入集群,从而避免产生脑裂。
入口:ZenDiscovery#handleNodeFailure
最终调用到:NodeRemovalClusterStateTaskExecutor#execute
在这里插入图片描述

3.4.2 MasterFaultDetection

master掉线则比较简单,剩下的节点需要重新加入集群,重新走一次选主流程。
入口:
在这里插入图片描述

4 可能发生选主的情况

总结,什么时候可能出发选主:

  1. 集群启动
  2. Master探测到节点掉线
  3. 非Master探测到Master掉线
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值