留意Elasticsearch 7.x 可能无法选主的问题

留意Elasticsearch 7.x 可能无法选主的问题

Elasticsearch 7.x 选举算法改为基于 Raft 的实现,与标准 Raft 相比,最大的区别是允许选民可以投多票,当产生多个主节点的时候,让最后一个当选,这样,可以更快地选出主节点。但是这种机制同样也有缺点,就是会使竞选过程比较激烈。特别是当集群节点数量比较多的时候,候选人反复竞争可能会持续很长时间。

当遇到这种情况时,节点会有如下的日志:

master not discovered or elected yet, an election requires at least XX nodes with ids from [] which is a quorum; discovery will continue using [] from hosts providers and [] from last-known cluster state; node term 14, last-accepted version 71 in term 5

以及:

failed to join{…}
CoordinationStateRejectedException: incoming term 4996 does not match current term

但是这些报错和问题根因没有啥关系,探测到的节点已经能够达到 quorum,然后继续discovery,让人很费解。这时得把日志调到 DEBUG:

跟随报错日志”which is a quorum; discovery will“,从代码一路跟过去,发现只有becomeCandidate的时候才会触发,搜索 debug 日志”coordinator becoming CANDIDATE“,找到以下信息:

注意他上一个状态是FOLLOWER,在 Elasticsearch 的选举状态图里,只有加入集群才会切换到FOLLOWER状态。这说明有主节点被选出来了,继续搜 ”coordinator becoming FOLLOWER “,可以找到他切换到FOLLOWER时Leader的源地址:

然后看一下 Leader 节点的日志,发现有:

可以看到节点起初被成功选为 Master,但是后来因为收到其他节点拉选票的RequestVote 请求(joinLeaderInTerm函数是对竞选请求的处理)取消集群状态的发布,切换到候选人状态。如果他成功发布了集群状态,新主就可以顺利当选了。

我们再观察候选人每次发起 RequestVote 的周期以及成功情况:

发现他有时候甚至来不及被选为master,都没有走到发布集群状态的流程:

而来不及被选为 master 的原因是被其他候选人拉选票的请求打断:

在 Elasticsearch 的选举算法中,允许选民投多票,并让最后一个leader当选,这需要

  • 候选人在拉选票的过程中,如果收到其他候选人的 RequestVote,则清空自己已经收到的选票
  • 如果一个 leader 收到 RequestVote,则切换到候选人

决定竞选激烈程度的是几个超时时间控制的选举周期:

  • gracePeriod:固定的竞选时长限制,由cluster.election.duration配置,默认 500ms
  • maxTimeout:选举前的最大等待时间,由cluster.election.max_timeout配置,默认 10s
  • backoffTime:竞选失败进行重试时,用重试次数乘以 backoffTime,由cluster.election.back_off_time
    配置,默认 100ms

候选人的竞选过程周期性执行,执行周期就是在cluster.election.duration的基础上加上不超过最大等待时间的随机值。

这个延迟时间是一个比较小的时间,我们截取两个时间点可以大致看一下增长情况,经过 4 分钟左右,竞选周期从 1 秒内增长到 7 秒。这个过程是线性增长的。

[2021-02-18T00:13:48,869][DEBUG]scheduleNextElection{ delayMillis=658}
[2021-02-18T00:17:53,743][DEBUG]scheduleNextElection{ delayMillis=7597}

从上面的实现可以看出,加大 cluster.election.duration可以降低选举激烈程度。

这里还有一个疑问,PreVote 是干什么去了,为什么没有拦截住?有两种情况:

  • 选民收到首次集群状态,才认为集群存在 Leader 了,后续的 Prevote 返回 false,但是在竞争激烈的时候没有节点被选为 leader。
  • 选民收到了首次集群状态,但在此之前又收到了其他节点的 RequestVote,导致自己的 term 更大了,首次集群状态因为 term 更低被忽略。如下图:

最后总结一下,虽然分析过程比较复杂,但是解决起来比较简单(不很完美):部署独立的主节点,并且可以考虑适当增大cluster.election.duration的配置

(转载请注明作者和出处 easyice.cn ,请勿用于任何商业用途)

1 Star2 Stars3 Stars4 Stars5 Stars (欢迎评分)
Loading...

发表评论

邮箱地址不会被公开。 必填项已用*标注