- 一、简介
- 二、设计思想
- 三、为什么使用主从模式
- 四、选举算法
- 4.1、Bully算法
- 4.2、Paxos算法
- 五、相关配置
- 六、流程分析
- 6.0、流程概述
- 6.0.1、ZenDiscovery的选主过程如下:
- 6.0.2、整体流程可以概括为:
- 6.1、选举临时Master
- 6.1.1、从`masterCandidates`中选主
- 6.1.2、投票与得票的实现
- 6.1.3、确立Master或加入集群
- 6.1.3.1、如果临时Master是本节点:
- 6.1.3.2、如果其他节点被选为Master:
- 6.2、节点失效检测
- 6.2.1、NodesFaultDetection 事件处理
- 6.2.2、MasterFaultDetection事件处理
- 小结
- 关注我的公众号【宝哥大数据】,更多干货
Discovery 模块负责发现集群中的节点,以及选择主节点。ES 支持多种不同 Discovery 类型选择,内置的实现称为Zen Discovery
,其他的包括公有云平台亚马逊的EC2、谷歌的GCE等。
本章讨论内置的 Zen Discovery 实现。Zen Discovery 封装了节点发现(Ping)、选主等实现过程,现在我们先讨论选主流程,在后面的章节中整体性介绍Discovery模块。
二、设计思想所有分布式系统都需要以某种方式处理一致性问题。一般情况下,可以将策略分为两组:
- 试图避免不一致
- 及定义发生不一致之后如何协调它们。后者在适用场景下非常强大,但对数据模型有比较严格的限制。因此这里研究前者,以及如何应对网络故障。
除主从(Leader/Follower) 模式外,另一种选择是分布式哈希表(DHT),可以支持每小时数千个节点的离开和加入,其可以在不了解底层网络拓扑的异构网络中工作,查询响应时间大约为4到10跳(中转次数),例如,Cassandra 就使用这种方案。但是在相对稳定的对等网络中,主从模式会更好。
ES的典型场景中的另一个简化是集群中没有那么多节点。通常,节点的数量远远小于单个节点能够维护的连接数,并且网络环境不必经常处理节点的加入和离开。这就是为什么主从模式更合适ES。
四、选举算法在主节点选举算法的选择上,基本原则是不重复造轮子。最好实现一个众所周知的算法,这样的好处是其中的优点和缺陷是已知的。ES的选举算法的选择上主要考虑下面两种。
4.1、Bully算法Leader 选举的基本算法之一。它假定所有节点都有一个唯一的 ID,使用该ID对节点进行排序。任何时候的当前Leader都是参与集群的最高ID节点。 该算法的优点是易于实现。但是,当拥有最大ID的节点处于不稳定状态的场景下会有问题。例如,Master 负载过重而假死,集群拥有第二大ID的节点被选为新主,这时原来的Master恢复,再次被选为新主,然后又假死…
ES通过推迟选举,直到当前的Master 失效来解决上述问题,只要当前主节点不挂掉,就不重新选主。但是容易产生脑裂(双主),为此,再通过“法定得票人数过半”解决脑裂问题。
4.2、Paxos算法Paxos非常强大,尤其在什么时机,以及如何进行选举方面的灵活性比简单的Bully算法有很大的优势,因为在现实生活中,存在比网络连接异常更多的故障模式。但Paxos实现起来非常复杂。
五、相关配置与选主过程相关的重要配置有下列几个,并非全部配置。
discovery.zen.minimum_master_nodes
:最小主节点数,这是防止脑裂、防止数据丢失的极其重要的参数。这个参数的实际作用早已超越了其表面的含义。除了在选主时用于决定“多数”,还用于多处重要的判断,至少包含以下时机:
- 触发选主: 进入选主的流程之前,参选的节点数需要达到法定人数。
- 决定Master: 选出临时的Master之后,这个临时Master需要判断加入它的节点达到法定人数,才确认选主成功。
- gateway选举元信息: 向有 Master 资格的节点发起请求,获取元数据,获取的响应数量必须达到法定人数,也就是参与元信息选举的节点数。
- Master发布集群状态: 发布成功数量为多数。
为了避免脑裂,它的值应该是半数以上(quorum):(master_eligible_nodes /2)+1
例如:如果有3个具备Master资格的节点,则这个值至少应该设置为(3/2) + 1=2。
该参数可以动态设置:
PUT /_cluster/settings
{
"persistent" : {
"discovery.zen.minimum master_nodes" : 2
}
}
discovery.zen.ping.unicast.hosts
:**集群的种子节点列表,构建集群时本节点会尝试连接这个节点列表,那么列表中的主机会看到整个集群中都有哪些主机。**可以配置为部分或全部集群节点。可以像下面这样指定:
discovery.zen.ping.unicast.hosts:
- 192.168.1.10:9300
- 192.168.1.11
- seeds.mydomain.com
默认使用9300端口,如果需要更改端口号,则可以在IP后手工指定端口。也可以设置一个域名,让该域名解析到多个IP地址,ES会尝试连接这个IP列表中的全部地址。
discovery.zen.ping.unicast.hosts.resolve_timeout: DNS
解析超时时间,默认为5秒。discovery.zen.join_timeout
: 节点加入现有集群时的超时时间,默认为ping_ timeout的20倍。discovery.zen.join_retry_attemptsjoin_timeout
:超时之后的重试次数,默认为3次。discovery.zen.join_retry_delayjoin_timeout
:超时之后,重试前的延迟时间,默认为100毫秒。discovery.zen.master_election.ignore_non_master_ pings
:设置为true时,选主阶段将忽略来自不具备Master资格节点(node.master: false)的ping请求,默认为false。discovery.zen.fd.ping_interval
:故障检测间隔周期,默认为1秒。discovery.zen.fd.ping_timeout
:故障检测请求超时时间,默认为30秒。discovery.zen.fd.ping_retries
:故障检测超时后的重试次数,默认为3次。
- 每个节点计算最小的已知节点 ID,该节点为临时Master。向该节点发送领导投票。
- 如果一个节点收到足够多的票数,并且该节点也为自己投票,那么它将扮演领导者的角色,开始发布集群状态。
- 所有节点都会参与选举,并参与投票,但是,只有有资格成为Master的节点(node.maste为true)的投票才有效。
获得多少选票可以赢得选举胜利,就是所谓的法定人数。在ES中,法定大小是一个可配置的参数。配置项: discovery.zen.minimum master_ nodes
。 为了避免脑裂,最小值应该是有Maste资格的节点数n/2+1
。
- 选举临时Master;
- 投票-确认Master,如果本节点当选,则等待确立Master,如果其他节点当选,则尝试加入集群,然后启动节点失效探测器;
- 失效节点探测;
具体如下图所示。
执行本流程的线程池: generic。
下面我们具体分析每个步骤的实现。
6.1、选举临时Master选举过程的实现位于ZenDiscovery#findMaster
。 该函数查找当前集群的活跃Master,或者从候选者中选择新的Master。如果选 主成功,则返回选定的Master,否则返回空。
为什么是临时Master?因为还需要等待下一个步骤,该节点的得票数足够时,才确立为真正的Master。
临时Master的选举过程如下:
- "ping"所有节点,获取节点列表 fullPingResponses, ping结果不包含本节点,把本节点单独添加到fullPingResponses中。
- 构建两个列表。
- activeMasters列表: 存储集群当前活跃Master列表。
- masterCandidates列表: 存储master候选者列表
activeMasters列表:存储集群当前活跃Master列表。 遍历第一步 获取的所有节点,将每个节点所认为的当前Master节点加入activeMasters 列表中(不包括本节点)。在遍历过程中,如果配置了discovery.zen.master_election.ignore_non_master_pings
为true ( 默认为false),而节点又不具备Master资格,则跳过该节点。
具体流程如下图所示。
这个过程是将集群当前已存在的Master加入activeMasters列表,正常情况下只有一个。如果集群已存在Master,则每个节点都记录了当前Master是哪个,考虑到异常情况下,可能各个节点看到的当前Master不同。在构建activeMasters列表过程中,如果节点不具备Master资格,则可以通过ignore_non_master_pings
选项忽略它认为的那个Master。
masterCandidates列表:存储master候选者列表。 遍历第一步获取列表,去掉不具备Maste资格的节点,添加到这个列表中。如果activeMasters为空,则从masterCandidates中选举,结果可能选举成功,也可能选举失败。如果不为空,则从activeMasters中选择最合适的作为Master。
整体流程如下图所示。
masterCandidates
中选主
与选主的具体细节实现封装在 ElectMasterService 类中,例如,判断候选者是否足够,选择具体的节点作为Master等。
从 masterCandidates 中选主时,首先需要判断当前候选者人数是否达到法定人数,否则选主失败。
public boolean hasEnoughCandidates (Collection candidates) {
//候选者为空,返回失败
if (candidates.isEmpty()) {
return false;
}
//默认值为-1, 确保单节点的集群可以正常选主
if (minimumMasterNodes = minimumMasterNodes;
}
当候选者人数达到法定人数后,从候选者中选一个出来做Master:
public MasterCandidate electMaster (Collection candidates) {
List sortedCandidates = new ArrayList (candidates);
//通过自定义的比较函数对候选者节点从小到大排序
sortedCandidates.sort (MasterCandidate :: compare);
//返回最新的作为Master
return sortedCandidates.get(0);
}
可以看出这里只是将节点排序后选择最小的节点作为Master。但是排序时使用自定义的比较函数MasterCandidate::compare,早期的版本中只是对节点ID进行排序,现在会优先把集群状态版本号高的节点放在前面。
使用默认比较函数的情况下,sort结果为从小到大排序。参考Long类型的比较函数的实现:
public static int compare (1ong X,long y) {
return(x
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?