Discovery模块负责发现集群中的节点,以及选择主节点
ES支持多种不同Discovery类型选择,内置的实现称为Zen Discovery,其他的包括公有云平台亚马逊的EC2、谷歌的GCE等。本文讨论内置的Zen Discovery实现。
Zen Discovery封装了节点发现(Ping)、选主等实现过程,现在我们先讨论选主流程,在后面的文章中整体性介绍Discovery模块。

设计思想

所有分布式系统都需要以某种方式处理一致性问题。
一般情况下,可以将策略分为两类:如何避免不一致 和 定义发生不一致之后如何协调它们。
后者在适用场景下非常强大,但对数据模型有比较严格的限制。因此本文研究前者,以及如何应对网络故障。

为什么选择主从模式

除主从(Leader/Follower)模式外,另一种选择是分布式哈希表(DHT),可以支持每小时数千个节点的离开和加入,其可以在不了解底层网络拓扑的异构网络中工作,查询响应时间大约为4到10跳(中转
次数),例如,Cassandra就使用这种方案。
但是在相对稳定的对等网络中,主从模式会更好。
ES的典型场景中的另一个简化是集群中没有那么多节点。通常,
节点的数量远远小于单个节点能够维护的连接数,并且网络环境不必
经常处理节点的加入和离开。这就是为什么主从模式更适合ES。

选举算法

在主节点选举算法的选择上,基本原则是不重复造轮子。最好实现一个众所周知的算法,这样的好处是其中的优点和缺陷是已知的。
ES的选举算法的选择上主要考虑下面两种。

Bully算法

Leader选举的基本算法之一。它假定所有节点都有一个唯一的ID,使用该ID对节点进行排序。
任何时候的当前Leader都是参与集群的最高ID节点
该算法的优点是易于实现
但是,当拥有最大ID的节点处于不稳定状态的场景下会有问题。
例如,Master负载过重而假死,集群拥有第二大ID的节点被选为新主,这时原来的Master恢复,再次被选为新主,然后又假死……
ES 通过推迟选举,直到当前的 Master 失效来解决上述问题只要当前主节点不挂掉,就不重新选主
但是容易产生脑裂(双主),为此,再通过“法定得票人数过半”解决脑裂问题

Paxos算法

Paxos非常强大,尤其在什么时机选举,以及如何进行选举方面的灵活性比简单的Bully算法有很大的优势,因为在现实生活中,存在比网络连接异常更多的故障模式。但 Paxos 实现起来非常复杂。

相关配置

与选主过程相关的重要配置有下列几个(并非全部配置)。

discovery.zen.minimum_master_nodes

最小主节点数,这是防止脑裂、防止数据丢失的极其重要的参数。这个参数的实际作用早已超越了其表面的含义。除了在选主时用于决定“多数”,还用于多处重要的判断,至少包含以下时机:

  • 触发选主:进入选主的流程之前,参选的节点数需要达到法定人数。
  • 决定Master:选出临时的Master之后,这个临时Master需要判断加入它的节点达到法定人数,才确认选主成功。
  • gateway选举元信息:向有Master资格的节点发起请求,获取元数据,获取的响应数量必须达到法定人数,也就是参与元信息选举的节点数。
  • Master发布集群状态:发布成功数量为多数。

为了避免脑裂,它的值应该是半数以上(quorum):(master_eligible_nodes / 2) + 1;
该参数可以动态设置:

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_attempts join_timeout:超时之后的重试次数,默认为3次。
  • discovery.zen.join_retry_delay join_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次。

选举流程概述

ZenDiscovery的选主过程如下:

  • 每个节点计算最小的已知节点ID,该节点为临时Master。向该节点发送领导投票
  • 如果一个节点收到足够多的票数,并且该节点也为自己投票,那么它将扮演领导者的角色,开始发布集群状态。

所有节点都会参与选举,并参与投票,但只有有资格成为Master的节点(node.master为true)的投票才有效
获得多少选票可以赢得选举胜利,就是所谓的法定人数
在 ES中 , 法定大小是一个可配置的参数。 配置项:discovery.zen.minimum_master_nodes
为了避免脑裂,最小值应该是有Master资格的节点数n/2+1