DDIA 对 Raft 的这种极端场景的描述,要如何理解?

开发 后端
Raft 算法存在一种失去活性(liveness)的极端情况:如果有一条网络连接不可靠,Raft 当前领导者会不断被迫下台导致系统实质上毫无进展。

[[421736]]

本文选自我在知乎的回答。

《设计数据密集型应用》(即 DDIA)中提到 Raft 的一个问题,即,Raft 算法存在一种失去活性(liveness)的极端情况:如果有一条网络连接不可靠,Raft 当前领导者会不断被迫下台导致系统实质上毫无进展。

我们先来具体描述一下该问题。

如图所示的 4 节点 Raft 集群,其中有一个节点和其他三个网络不太稳定,假设它能发送消息给别的节点但收不到其他节点的消息,那么它就会一直收不到心跳消息,然后转为 candidate 自增任期并发起新的选举,来自更大任期的 RequestVote 请求会导致现在的 Leader 下台重新选举。这样一直反复,会导致集群无法正常工作。

Raft 大论文提到一种解决方式是加入一个新的 PreVote 阶段,etcd 就这么干了,为此增加了一种新的节点状态叫做 PreCandidate 状态。

PreVote 阶段作用是当一个节点想要发起选举时,首先要确认自己确实有资格赢得投票而不是在浪费时间,才会真的自增任期发起新的选举。

PreVote 阶段的具体流程是,在发起真正的选举之前,先发送 PreVote 消息给所有节点, PreVote消息和 RequestVote 消息一样,但节点不会自增自己的任期,只会增加消息中的 term 参数。

收到 PreVote 消息的节点同意重新选举的条件是:

参数中的任期更大,或者任期相同但 log index 更大;

至少一次 election timeout 时间内没有收到领导者心跳;

只有超过半数节点同意 PreVote 消息,该节点才能真正去自增任期并发起新的选举。

回到上述情况,网络链路有问题的那个节点在 PreVote 阶段会发现自己无法赢得超过半数节点同意自己发起选举(别的节点都能收到心跳),因此不会自增任期去干扰 Leader 工作。

问题解决了吗?

问题并没有解决,只有 PreVote 阶段还可能有一种极端情况会导致 Raft 失去活性。如图所示:

图中是一个 5 节点组成的 Raft 集群,故障发生之前 4 是 Leader。现在故障发生了,5 宕机了,同时 4 只和 2 保持连接,1、2、3互相保持连接。这种情况下 1、3 收不到 Leader 的心跳,会发起 PreVote请求,但由于 2 能收到 Leader 节点 4 的心跳,所以 2 不会同意 PreVote 请求,因此节点 1、3 无法获得多数派的 PreVote 同意。

该集群的问题是,无法选举出新的 Leader,但旧的 Leader 又只能 AppendEntries 到两个节点(2和自己),无法达成多数派,整个集群无法取得任何进展,不满足活性。

此处 Raft 协议明明可以容忍 2 个节点故障,但增加了 PreVote 阶段后反而无法容忍仅仅 1 个节点故障,其实没有 PreVote 阶段的话,1 和 3 是有机会当选 Leader 推进整个系统正常工作的。

因此 Raft 还需要增加一种机制来让 Leader 主动下台。

这个机制很简单:Leader 没有收到来自多数派节点的 AppendEntries 响应时就主动下台。这样,图中 1、2 和 3 都有机会当选新的 Leader,整个集群依旧可以正常工作。

etcd 把这叫做 CheckQuorum,etcd 的 issue 中有关于此问题的讨论:https://github.com/etcd-io/etcd/issues/3866

CheckQuorum 确保了如果当前 Leader 无法连接到多数派节点,它将会下台并选举出新的 Leader。PreVote 确保一旦 Leader 当选,整个系统将是稳定的,Leader 不会被迫下台。

那么 PreVote + CheckQuorum 可以解决活性问题了吗?

 

可以了!

 

责任编辑:武晓燕 来源: 多颗糖
相关推荐

2024-05-08 08:18:05

索引失效场景

2021-09-29 07:24:20

场景数据

2021-09-28 07:12:09

测试路径

2021-06-18 08:04:46

Linux进程操作系统

2010-08-02 08:40:43

DB2数据库性能

2021-10-09 10:25:41

排序应用场景

2021-10-08 09:59:32

冒泡排序场景

2021-10-13 18:01:33

快速排序场景

2021-10-11 09:38:41

开源

2021-10-12 07:15:02

归并排序场景

2021-09-16 07:52:18

算法应用场景

2010-05-26 15:03:51

2013-05-13 09:35:03

微软Windows 8弗兰克·肖称

2021-10-14 07:55:20

二分查找面试

2021-11-10 07:47:49

组合模式场景

2021-11-03 14:10:28

工厂模式场景

2021-08-16 08:33:26

git

2015-12-09 13:06:15

Linux架构内核

2021-11-09 08:51:13

模式命令面试

2021-11-05 07:47:56

代理模式对象
点赞
收藏

51CTO技术栈公众号