Elasticsearch中Discovery模块负责发现集群中的节点以及Master的选举,其默认的实现称为Zen Discovery。
在Elasticsearch的配置文件中,有一项为node.master,如果将该配置设为true,该节点即可参与Master选举,获得被选举为Master节点的资格。
Master选举算法
(1)Paxos算法
Paxos算法在分布式系统中是一种比较著名的选举算法,并且非常强大,但是它实现比较复杂,这里不过多讲解。
(2)Bully算法
Bully算法假设集群中所有的节点都有一个唯一的ID,通过对ID进行排序,选取ID最大的节点作为Master节点。
brain-split问题
一个集群建立起之后会选出一个master,负责管理整个集群,当master负载比较大时或者产生网络分区时,导致其他节点可能认为master节点已失效,从而选举新的节点,出现多个master的情况,这就是brain-split问题。
ES在选举master时,获得的投票数必须要达到quorum也就是参选人数需要过半,才能确认Master,quorum的数量可以在配置文件中配置discovery.zen.minimum_master_nodes,一般配置数量为集群中具有master资格的节点数除以2加1:
1 | discovery.zen.minimum_master_nodes: 1 |
Elasticsearch Master选举流程
Elasticsearch基于Bully算法,选举流程如下:
1.Ping所有的节点,选举临时的Master
- fullPingResponses
选举过程的实现位于ZenDiscovery类的findMaster方法中,在该方法中首先Ping集群中的所有节点,得到返回结果fullPingResponses,fullPingResponses是由集群中的节点组成的列表,但是不包含当前的节点,当前节点单独被添加到fullPingResponses中。接着,将discovery.zen.master_election.ignore_non_master_pings为true并且不具备Master资格的节点过滤掉,并放入pingResponses中。
- activeMasters
activeMasters存储当前活跃的Master列表,它是通过遍历pingResponses,将每个节点认为的Master节点(并且不是当前节点)加入到activeMasters列表中。
- masterCandidates
masterCandidates存储Master候选者列表,也就是具有Master资格的节点,它也是通过遍历pingResponses,判断每个节点是否具有Master资格得到的候选者列表。
1 | public class ZenDiscovery extends AbstractLifecycleComponent implements Discovery, PingContextProvider, IncomingClusterStateListener { |
具体选举过程
首先判断activeMasters是否为空,如果不为空,从activeMasters选举。如果为空,判断masterCandidates中候选者是否达到了法定人数 quorum,如果达到,从中选举Master节点,如果未到达,重新获取节点。
(1)从masterCandidates选举
具体的实现在ElectMasterService中:
判断是否到达法定人数
- 判断masterCandidates是否为空,为空返回false
- 判断discovery.zen.minimum_master_nodes配置的值(默认值为-1)是否小于1,确保单节点情况下的正常选主
- 判断masterCandidates中具备master资格的节点数据是否大于等于minimum_master_nodes
选举临时Master
- 首先对masterCandidates中的节点进行排序,优先使用版本号,版本号最高的排在前面,如果版本号一致,再跟进节点ID进行排序,节点ID小的排在前面
- 返回排序后最前面的节点,也就是第一个节点作为Master节点
1 | public class ElectMasterService extends AbstractComponent { |
(2)从activeMasters选举
从activeMasters选举的过程比较简单,具体的实现也在ElectMasterService中。首先通过compareNodes方法对节点ID排序,然后取节点ID最小的作为临时的Master。
1 | public class ElectMasterService extends AbstractComponent { |
2.确立Master
上一步选举出的临时的Master有两种情况,临时Master就是当前节点或者临时Master不是当前节点。
在ES中,向节点发送join请求就是发送投票,被发送请求的节点将会得到一票。
(1)临时Master节点为当前节点
- 等待足够多的具有Master资格的节点加入本节点,达到法定人数的投票数量时完成选主
- 如果等待超时后还没有满足法定数量,选举失败,将会进行新一轮的选举
- 如果选主成功,将会发布新的cluster state version
ZenDiscovery
1 | public class ZenDiscovery extends AbstractLifecycleComponent implements Discovery, PingContextProvider, IncomingClusterStateListener { |
(2)临时Master节点不是当前节点
- 当前节点停止接收其他节点的join请求
- 最终当选的Master会先发布集群状态,之后确认其他节点的join请求。
- 当前节点向Master节点发送join请求,并且等待Master的回复(默认为1分钟),如果失败重新发送join请求(默认重试3次),如果回复成功,从集群中获取Master节点,判断与临时Master是否一致,如果不一致重新选举。
1 | public class ZenDiscovery extends AbstractLifecycleComponent implements Discovery, PingContextProvider, IncomingClusterStateListener { |
投票与得票的实现
在确定Master节点的时候,如果推选的临时Master为当前节点,有一步是调用waitToBeElectedAsMaster方法,等待当前节点被推举为真正的Master节点,借助waitToBeElectedAsMaster方法看一下投票与得票的实现。
NodeJoinController
1 | public class NodeJoinController extends AbstractComponent { |
参考:
Elasticsearch源码解析与优化实战【张超】
Elasticsearch分布式一致性原理剖析(一)-节点篇
Elasticsearch版本:6.1.2