Raft

参考动画更容易理解:http://thesecretlivesofdata.com/raft/(自备梯子)

Raft中领导者选举流程

假设现在集群中有三个节点:A,B,C。三个节点的状态都是Follower状态。

对于某一个节点来说,如果收不到Leader的通信,那么将会变成Candidate状态。

Candidate节点会发送投票给其他节点,其他节点也会回复投票。如果Candidate节点接收到大多数节点的投票,那么它将成为Leader。

Raft中处理请求流程

集群中任何数据的变动都要经过Leader。

某一个节点接收到一个客户端变更数据请求时,会先生成一个条目添加到节点的日志文件中。这个日志条目是未提交的,因此暂时并没有真正修改节点的数据。

想要提交这个日志条目的第一步是:把这个日志条目复制给其他Follower节点。然后Leader开始等待,直到大多数Follower节点把日志条目都写进各自的日志文件了。

然后Leader节点提交刚刚的日志条目,也就是真正引起数据的变更,并且通知其他Follower也可以提交了。

其他Follower节点提交后,整个集群数据就达到了一致。

领导者选举详细步骤

在Raft中有两个超时时间设置用来控制选举。

第一个就是选举超时时间。表示一个Follower节点等待这段时间后将变为Candidate状态。每个节点的选举超时时间是随机的,在150ms到300ms直接随机。

某一个节点超过选举超时时间后,会成为Candidate节点,就会开始新一轮选举了。

  1. 投给自己
  2. 发送投票给其他节点
  3. 如果接收到该投票的其他节点,在本轮选举中还没有投票,则会投给该Candidate节点,并且重置各自的选举超时时间
  4. 如果Candidate节点收到超过一半的投票,那么它将成为Leader
  5. Leader开始发送追加条目(起心跳作用)给其他Follower节点,这些条目会定时发送,该时间是心跳超时时间
  6. Follower节点每接收到一个心跳,就会重置选举超时时间, 并且响应每个追加条目
  7. 当某个Follower节点接收不到心跳了,那么它就会变成Candidate节点,从而开始新一轮领导者选举

Leader需要获取超过一半的投票,这样可以确保每个选举周期只能选出一位领导人。

如果有两个节点同时成为了Candidate节点,如果这两个节点收到的投票数是一样的话,那么暂时选不出来Leader,在这种情况下,会出现第三个Candidate节点,重新开始一轮新的选举,然后成为Leader。

Raft中处理请求流程详解

现在,集群中已经存在一个Leader了。并且Leader节点会和其他Follower节点维持心跳。

  1. Leader节点接收到一个数据变更请求后,会生成一条日志在Leader节点的日志文件中。
  2. 并且在下一次心跳时,把这个日志文件复制发送给其他Follower节点。
  3. 当收到大部分Follower节点的确认后,Leader节点进行提交,也就是真正修改数据。
  4. 最后,响应客户端。

在面对网络分区时,Raft也能保证集群中的数据一致性。因为当网络分区后,比如分成两个分区,那么这两个分区中的节点个数,要么各占一半,要么其中某个分区的节点数比另外一个分区的节点数更多一点的。

在这种情况下,如果各占一半,那么拥有Leader节点的分区仍然正常工作,而另外一个分区会尝试进行领导者选举,但是选不出来。

如果拥有Leader节点的分区内有较多的节点个数,那么另外一个分区也选不出来Leader。

如果拥有Leader节点的分区内有较少的节点个数,那么另外一个分区将选出来一个Leader,这个时候另外一个分区能正常工作,而原Leader节点所在分区是不能处理请求的,因为在处理请求时也需要拥有大多数节点的确认。