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节点,就会开始新一轮选举了。
- 投给自己
- 发送投票给其他节点
- 如果接收到该投票的其他节点,在本轮选举中还没有投票,则会投给该Candidate节点,并且重置各自的选举超时时间
- 如果Candidate节点收到超过一半的投票,那么它将成为Leader
- Leader开始发送追加条目(起心跳作用)给其他Follower节点,这些条目会定时发送,该时间是心跳超时时间。
- Follower节点每接收到一个心跳,就会重置选举超时时间, 并且响应每个追加条目
- 当某个Follower节点接收不到心跳了,那么它就会变成Candidate节点,从而开始新一轮领导者选举
Leader需要获取超过一半的投票,这样可以确保每个选举周期只能选出一位领导人。
如果有两个节点同时成为了Candidate节点,如果这两个节点收到的投票数是一样的话,那么暂时选不出来Leader,在这种情况下,会出现第三个Candidate节点,重新开始一轮新的选举,然后成为Leader。
Raft中处理请求流程详解
现在,集群中已经存在一个Leader了。并且Leader节点会和其他Follower节点维持心跳。
- Leader节点接收到一个数据变更请求后,会生成一条日志在Leader节点的日志文件中。
- 并且在下一次心跳时,把这个日志文件复制发送给其他Follower节点。
- 当收到大部分Follower节点的确认后,Leader节点进行提交,也就是真正修改数据。
- 最后,响应客户端。
在面对网络分区时,Raft也能保证集群中的数据一致性。因为当网络分区后,比如分成两个分区,那么这两个分区中的节点个数,要么各占一半,要么其中某个分区的节点数比另外一个分区的节点数更多一点的。
在这种情况下,如果各占一半,那么拥有Leader节点的分区仍然正常工作,而另外一个分区会尝试进行领导者选举,但是选不出来。
如果拥有Leader节点的分区内有较多的节点个数,那么另外一个分区也选不出来Leader。
如果拥有Leader节点的分区内有较少的节点个数,那么另外一个分区将选出来一个Leader,这个时候另外一个分区能正常工作,而原Leader节点所在分区是不能处理请求的,因为在处理请求时也需要拥有大多数节点的确认。