MIT6.824/lecture-06-raft1/6.8-xuan-ju-ding-shi-qi-election-timer.md
2022-01-25 02:41:31 +00:00

6.8 KiB
Raw Permalink Blame History

6.8 选举定时器Election Timer

(选举定时器在上一篇有过一些介绍)

任何一条AppendEntries消息都会重置所有Raft节点的选举定时器。这样只要Leader还在线并且它还在以合理的速率不能太慢发出心跳或者其他的AppendEntries消息Followers收到了AppendEntries消息会重置自己的选举定时器这样Leader就可以阻止任何其他节点成为一个候选人。所以只要所有环节都在正常工作不断重复的心跳会阻止任何新的选举发生。当然如果网络故障或者发生了丢包不可避免的还是会有新的选举。但是如果一切都正常我们不太可能会有一次新的选举。

如果一次选举选出了0个Leader这次选举就失败了。有一些显而易见的场景会导致选举失败例如太多的服务器关机或者不可用了或者网络连接出现故障。这些场景会导致你不能凑齐过半的服务器进而也不能赢得选举这时什么事也不会发生。

一个导致选举失败的更有趣的场景是所有环节都在正常工作没有故障没有丢包但是候选人们几乎是同时参加竞选它们分割了选票Split Vote。假设我们有一个3节点的多副本系统3个节点的选举定时器几乎同超时进而期触发选举。首先每个节点都会为自己投票。之后每个节点都会收到其他节点的RequestVote消息因为该节点已经投票给自己了所以它会返回反对投票。这意味着3个节点中的每个节点都只能收到一张投票来自于自己。没有一个节点获得了过半投票所以也就没有人能被选上。接下来它们的选举定时器会重新计时因为选举定时器只会在收到了AppendEntries消息时重置但是由于没有Leader所有也就没有AppendEntries消息。所有的选举定时器重新开始计时如果我们不够幸运的话所有的定时器又会在同一时间到期所有节点又会投票给自己又没有人获得了过半投票这个状态可能会一直持续下去。

Raft不能完全避免分割选票Split Vote但是可以使得这个场景出现的概率大大降低。Raft通过为选举定时器随机的选择超时时间来达到这一点。我们可以这样来看这种随机的方法。假设这里有个时间线我会在上面画上事件。在某个时间所有的节点收到了最后一条AppendEntries消息。之后Leader就故障了。我们这里假设Leader在发出最后一次心跳之后就故障关机了。所有的Followers在同一时间重置了它们的选举定时器因为它们大概率在同一时间收到了这条AppendEntries消息。

它们都重置了自己的选举定时器,这样在将来的某个时间会触发选举。但是这时,它们为选举定时器选择了不同的超时时间。

假设故障的旧的Leader是服务器1那么服务器2S2服务器3S3会在这个点为它们的选举定时器设置随机的超时时间。

假设S2的选举定时器的超时时间在这而S3的在这。

这个图里的关键点在于因为不同的服务器都选取了随机的超时时间总会有一个选举定时器先超时而另一个后超时。假设S2和S3之间的差距足够大先超时的那个节点也就是S2能够在另一个节点也就是S3超时之前发起一轮选举并获得过半的选票那么那个节点也就是S2就可以成为新的Leader。大家都明白了随机化是如何去除节点之间的同步特性吗

这里对于选举定时器的超时时间的设置需要注意一些细节。一个明显的要求是选举定时器的超时时间需要至少大于Leader的心跳间隔。这里非常明显假设Leader每100毫秒发出一个心跳你最好确认所有节点的选举定时器的超时时间不要小于100毫秒否则该节点会在收到正常的心跳之前触发选举。所以选举定时器的超时时间下限是一个心跳的间隔。实际上由于网络可能丢包这里你或许希望将下限设置为多个心跳间隔。所以如果心跳间隔是100毫秒你或许想要将选举定时器的最短超时时间设置为300毫秒也就是3次心跳的间隔。所以如果心跳间隔是这么多两个AE之间那么你会想要将选举定时器的超时时间下限设置成心跳间隔的几倍在这里。

那超时时间的上限呢?因为随机的话都是在一个范围内随机,那我们应该在哪设置超时时间的上限呢?在一个实际系统中,有几点需要注意。

首先这里的最大超时时间影响了系统能多快从故障中恢复。因为从旧的Leader故障开始到新的选举开始这段时间整个系统是瘫痪了。尽管还有一些其他服务器在运行但是因为没有Leader客户端请求会被丢弃。所以这里的上限越大系统的恢复时间也就越长。这里究竟有多重要取决于我们需要达到多高的性能以及故障出现的频率。如果一年才出一次故障那就无所谓了。如果故障很频繁那么我们或许就该关心恢复时间有多长。这是一个需要考虑的点。

另一个需要考虑的点是不同节点的选举定时器的超时时间差S2和S3之间必须要足够长使得第一个开始选举的节点能够完成一轮选举。这里至少需要大于发送一条RPC所需要的往返Round-Trip时间。

或许需要10毫秒来发送一条RPC并从其他所有服务器获得响应。如果这样的话我们需要设置超时时间的上限到足够大从而使得两个随机数之间的时间差极有可能大于10毫秒。

在Lab2中如果你的代码不能在几秒内从一个Leader故障的场景中恢复的话测试代码会报错。所以这种场景下你们需要调小选举定时器超时时间的上限。这样的话你才可能在几秒内完成一次Leader选举。这并不是一个很严格的限制。

这里还有一个小点需要注意,每一次一个节点重置自己的选举定时器时,都需要重新选择一个随机的超时时间。也就是说,不要在服务器启动的时候选择一个随机的超时时间,然后反复使用同一个值。因为如果你不够幸运的话,两个服务器会以极小的概率选择相同的随机超时时间,那么你会永远处于分割选票的场景中。所以你需要每次都为选举定时器选择一个不同的随机超时时间。