此前,在 rabbitmq 系列文章中,我们介绍过脑裂问题。
所谓的脑裂问题,就是在多机热备的高可用 HA 系统中,当两个节点心跳突然断开,就分裂为了两个独立的个体,由于互相失去联系,都认为对方出现了故障,因此都会去争抢对方的资源,争抢启动,由此就会发生严重的后果。 举个形象的例子,A 和 B 作为一个双机热备集群的两个节点,各自持有集群的一部分数据 — a 和 b,这时,两机器之间突然无法通信,A 认为 B 已经挂掉,B 认为 A 已经宕机,于是会出现:
Elasticsearch 也有可能发生这样的问题。
根据脑裂问题发生的两点原因,从集群搭建上需要遵循以下原则:
Elasticsearch 提供了以下配置,来决定该节点是否有成为 master 节点或数据节点的资格:
node.master: true node.data: false
这样配置,该节点将不会存储任何数据,将上述两项分别做相反配置,则节点只会成为数据节点,不会被选举为 Master 节点,这样就可以很大程度上保证集群的稳定性。
通常,我们只需要在每个节点配置好了集群名称,节点名称,互相通信的节点会根据es自定义的服务发现协议去按照多播的方式来寻找网络上配置在同样集群内的节点。 这就是多播模式,但事实上,在阿里云等云服务器上采用多播模式自行搭建 Elasticsearch 将导致各节点无法发现从而集群无法建成,这也是云服务供应商从安全角度考虑的策略,在这样的云服务器上,我们只能采用单播模式搭建集群。 所谓的单播,就是在配置中读取到 master 节点信息,直接连入,其效率和安全性都高于多播模式,但是单播存在的问题是如果新增节点是 master 候选节点,则必须更改集群中所有节点的配置。 下面的配置开启单播模式:
discovery.zen.ping.multicast.enabled: false discovery.zen.ping.unicast.hosts: ["master1", "master2", "master3"]
最少包含Master节点数与存活检测时长两个配置项也是避免脑裂问题的重要配置:
discovery.zen.minimum_master_nodes: 2 discovery.zen.ping_timeout: 60s
这个配置项就是最少包含 Master 节点数,他指的是集群中至少有多少个 master 候选节点存在才能组成集群。 官方推荐配置是 (N/2)+1,N 是 Master 候选节点总数量。 这样配置以后,假设集群从网络故障中恢复,若干个数据节点与 (N/2)+1 个 Master 候选节点组成了一个集群,剩余数据节点与剩余 master 候选节点尝试组成集群,由于剩余 Master 候选节点数为 N-((N/2)+1) = (N/2)-1 < (N/2)+1,所以他们不能成为一个集群,他们必须去继续寻找其他节点来组成集群,从而从根本上解决了脑裂问题。 这个配置也是几乎所有 HA 系统都会提供的基础配置。
这个配置是存活检测时长,意即超过该配置项的时间内节点没有响应,则认为该节点出现故障脱离集群,默认值为 3 秒。
适当增大该配置,可以降低误报的几率,减少 master 重新选举的可能。
对于 Elasticsearch 集群来说,是强烈不建议搭建仅具有两个节点的集群的,因为搭建两节点集群则必须在下列两个策略中选择其一:
如果在生产环境中,只有两台主机的环境下,更为推荐的做法是,在某一台主机上增加一份不同端口的设置:
node.data: false node.master: true
这样,在该主机上启动两个 Elasticsearch 实例,这样就可以创建一个具有三节点的集群,而数据的存储方式与此前的两节点集群保持一致。 当故障发生时,具有两节点的机器仍然可以提供集群服务,又可以避免脑裂问题,算是一种资源不足情况下的让步方案。
https://github.com/elastic/elasticsearch/issues/2488。 https://blog.csdn.net/cnweike/article/details/39083089。 https://www.cnblogs.com/zhukunrong/p/5224558.html。