3个PD的集群坏掉一个PD后,剩下两个PD还支持读写吧,它们是怎么选leader的?

raft的leader选举过程

何时发起选举

集群开始时,所有服务器都是follower,当服务器在指定的时间之内没有收到leader或者candidate的有效消息时会发起选举。这个指定的时间被称为election timeout,是一个随机的值(比如200ms-500ms)。什么是有效消息?leader的有效消息是指心跳消息,candidate的有效消息是指投票消息。这里引入了两个状态变量,election timeout和heartbeat time interval(leader发送心跳间隔时间),要求heartbeat time interval<<min(election timeout),避免follower重新发起无谓的投票。

投票过程

  1. follower递增自己的term。

  2. follower将自己的状态变为candidate。

  3. 投票给自己。

  4. 向集群其它机器发起投票请求(RequestVote请求)。

  5. 当以下情况发生,结束自己的candidate状态。

  6. 超过集群一半服务器都同意,状态变为leader,并且立即向所有服务器发送心跳消息,之后按照心跳间隔时间发送心跳消息。任意一个term中的任意一个服务器只能投一次票,所有的candidate在此term已经投给了自己,那么需要另外的follower投票才能赢得选举。

  7. 发现了其它leader并且这个leader的term不小于自己的term,状态转为follower。否则丢弃消息。

  8. 没有服务器赢得选举,可能是由于网络超时或者服务器原因没有leader被选举,这种情况比较简单,超时之后重试。有一种情况被称为split votes,比如一个有三个服务器的集群中所有服务器同时发起选举,那么就不可能有leader被选举出来,此时如果超时之后重试很可能所有服务器又同时发起选举,这样永远不可能有leader被选举出来。raft处理这种情况是采用上文提到过的random election timeout,随机超时保证了split votes发生的几率很小。

follower何时会同意

如果发起的投票请求包含的term大于等于当前term,并且日志信息不旧于candidate的日志信息,那么会同意。关于日志的相关信息,在log replication再讨论

term如何更新

所有请求和响应的接收方在接收到更大的term时都必须更新自己的term,这保证了投票最终能够选出一个leader。

3 个赞