关于raft:Raft算法之集群成员变化篇

60次阅读

共计 2195 个字符,预计需要花费 6 分钟才能阅读完成。

一、集群成员变动可能带来的问题

集群成员变动是一个常见操作,次要是减少、删除节点,次要的场景有降级、服务器老化等,当然如果咱们对服务的 SLA 没太大要求,间接敞开集群是最简略的方法。但如果要保证系统的可用性而动静地增加、删除节点并且保障不会脑裂等问题则须要一个平安的算法,所以 Raft 算法把这一部分也纳入其中。

间接将集群成员配置从旧配置切到新配置会有脑裂问题,举个例子:

上图中集群原来有 3 个节点:Server1、Server2、Server3,当初要减少 2 个节点:Server4、Server5,咱们来构想下具体的操作步骤:

1、Server4 和 Server5 是新节点,所以这 2 台机器启动的时候认为集群中有 5 个节点;

2、而后批改 Server3 的配置,改成 5 节点;

这时产生选举,即上图中红色箭头所指的地位,这时候每个节点看到的集群成员如下,为了不便形容,对立将 Server 字样去掉,即只保留 1、2、3、4、5,1 示意 Server1:

1:1、2、3

2:1、2、3

3:1、2、3、4、5

4:1、2、3、4、5

5:1、2、3、4、5

这时 1 通过 2 的投票能够被选举为 Leader,因为 1 和 2 认为集群只有 1、2、3 总共 3 个节点;

3 通过 3,4,5 这 3 个节点的投票被选举为 Leader;

这样集群同时存在 1 和 3 两个 Leader 了。

二、变更计划

官网给的计划是二阶段变更:

集群先从旧成员配置 Cold 切换到一个过渡成员配置,称为独特统一(joint consensus),独特统一是旧成员配置 Cold 和新成员配置 Cnew 的组合 Cold U Cnew,一旦独特统一 Cold U Cnew 被提交,零碎再切换到新成员配置 Cnew。

具体过程如下:

Leader 收到从 Cold 切成 Cnew 的成员变更申请,Leader 分两步操作:

1、提交配置 Cold U Cnew

Leader 在本地生成一个新的日志,这个日志的类型是成员配置,其内容是 Cold∪Cnew,代表以后时刻新旧成员配置共存,写入本地日志,但并不提交;

Leader 同时将该日志复制至 Cold∪Cnew 中的所有正本,在此之后新的日志同步须要保障失去 Cold 和 Cnew 两个多数派的确认;

Follower 收到 Cold∪Cnew 的日志后更新本地日志,并且 马上 就以该配置作为本人的成员配置;

如果 Cold 和 Cnew 中的两个多数派确认了 Cold U Cnew 这条日志,Leader 就提交这条日志;

2、提交 Cnew

接下来 Leader 生成一条新的日志条目,类型也是成员变更,其内容是新成员配置 Cnew,同样将该日志条目先写入本地日志,同时复制到 Follower 上;

Follower 收到新成员配置 Cnew 后,将其写入日志,并且 马上 就以该配置作为本人的成员配置,并且如果发现自己不在 Cnew 这个成员配置中会主动退出。

能够看到,Raft 算法将成员配置的变动也作为一条日志,须要通过一轮 Raft 过程像利用操作一样只有大多数节点确认了就必定不会出出脑裂了。留神 Follower 收到配置后马上就变更,而不须要等 Leader 下次发送 commitIndex 的时候才提交,这点是和失常利用提交不一样的中央。

这里不去做具体的证实,官网有具体阐明,咱们能够看下几个异样,还是以下面的例子,以后集群有 3 个节点:1、2、3,当初要减少 2 个节点:4、5,假如以后 Leader 为 1,具体过程如下:

1)节点 1 收到成员变更的申请,生成一条日志类型为成员变更,内容为:1、2、3、4、5,节点 1 将这条日志先保留到本地,但不马上更改成员配置;

2)节点 1 将上述日志同步给 2,3,4,5 四个节点;

3)2、3、4、5 节点收到配置后做 2 件事:追加日志,马上变更本人的成员配置为:1、2、3、4、5;

4)节点 1 只有收到 2 个以上节点回复马上将本人成员配置为:1、2、3、4、5.

咱们看有哪些异样:

如果有 1 - 2 过程中失败了,则整个过程就算失败,则须要管理员从新发动成员变更操作;

如果第 3 步只有 1 个节点即不是集群少数节点收到变更,这个时候节点 1 挂了,如果收到日志的先发动选举则有可能推动这条日志,否则就不胜利,即有可能失落;

如果在第 4 步节点 1 挂了的话,新集群必定是有这个配置的,因为依据日志最新准则,新选举进去的 Leader 必定蕴含下面成员变更的日志。

三、其它问题

1、新加的成员入无日志

一开始的时候新的服务器可能没有任何日志条目,如果它们在这个状态下退出到集群中,那么它们须要一段时间来更新追赶,在这个阶段它们还不能提交新的日志条目,这个时候节点没有投票权,有的文章说叫 Catch-Up。

2、移除不在 Cnew 中的服务器可能会扰乱集群

次要是移除的状况,构想一个集群有 5 个节点:1,2,3,4,以后 Leader 是 2,当初要把 1 移除掉,如果 2 曾经将新的成员配置:2,3,4 曾经同 步给 3 和 4 了,如果配置不发给 1,因为 2 认为集群中 1 不存在了,所以不会向 1 发心跳,而 1 没收到 2 的心跳,会减少本人的 Term 发动选举,其它成员收到后会进化成 Follower,不过不会给 1 投票,因为 1 的日志不是最新的,不过这会影响集群的可用性。

针对这个问题,官网给的是 PreVote,即在发动投票的 RequestVote RPC 申请之前再发一个 PreVote 申请,只有通过这个才正式发动 RequestVote,这样能够大大晋升零碎的可用性。其实还有 1 个更简略的方法,间接将 1 关机或者将服务程序 Kill 掉。

正文完
 0