1、一些概念
term: 任期
,比如新的选举任期,即整个集群初始化时,或者新的Leader选举就会开始一个新的选举任期。
大多数:
假设一个集群由N个节点组成,那么大多数就是至少N/2+1。例如:3个节点的集群,大多数就是至少2;5个节点的集群,大多数就是至少3。
状态:
每个节点有三种状态,且某一时刻只能是三种状态中的一种:Follower(图左),Candidate(图中),Leader(图右)。假设三种状态不同图案如下所示:
初始化状态时,节点都是 Follower
状态,并且 term
为0.
如果一段时间后,跟随者没有监听到领导者发来的消息,那么自己将变成候选人身份
2、Leader选取过程
完成选取后,所有的请求必定经过Leader节点
1、在Raft算法中,会有两个超时时间设置来控制选举过程:选举超时 和 心跳超时,其详细的解释在下一节。
初始状态下,所有节点会进入选举周期,都会在一个随机周期内变为候选节点。
2、当有节点成为候选节点,自然的会进入选取任期1,并且自然可以拿到自己的一个投票。
3、紧接着,候选节点会像其他所有节点发送投票请求,只有拿到大多数的选票才能成为Leader。
当然候选人也是不能重复投票的,在一个选取周期内,节点智能投出去一次。
注意:在 发送投票请求 和 响应请求 的时候节点都会启动 选取超时
4、如果候选节点能拿到过半数的投票,那就可以成为一个Leader。
注意:候选节点可能会同时存在多个,候选节点的票数也有可能出现一致的情况(一般偶数个节点会出现,所以节点数一般不要选偶数)。一次投票过程有且只能产生一个leader。
5、Leader选举成功后,Leader节点就会不断的往Follower节点发送附加日志。这些消息是周期性发送,也叫 心跳包
;当然在设值的时候,这个心跳包中也会附加同步操作。
6、选举周期将一直持续直到某个跟随者没有收到心跳包并成为候选人。
此时Node A就是 选取周期2的Leader了
至此最为普通的选举过程结束了。但是现实情况中还是可能同时存在两个候选节点的情况,或者网络分区导致有两个Leader的情况。
3、重新选取
两个候选节点的情况
1、在某种条件下,是会产生多个候选节点的,然后这两个候选节点会往A/C同时发送投票请求。
2、你说巧不巧,这个时候节点A投给了B,节点C投给了D。这种情况下B和D谁都不能拿到多数票,毕竟A、C同一时间只能投给一个节点。
3、这种情况下会重新进行一次竞选请求,这个就看这两个节点的随机函数结果了。
此时B的选取周期先结束,Node B就会被选为Leader。
4、两个超时
接下来介绍Raft中两个很重要的超时设置:
选举超时 和 心跳超时。
election timeout
,一般是150毫秒到300毫秒之间的随机数
heartbeat timeout
,视情况而定。
-
1、
选举超时
为了防止3个节点(假设集群由3个节点组成)同时发起投票,会给每个节点分配一个随机的选举超时时间(Election Timeout),即从Follower状态成为Candidate状态需要等待的时间。在这个时间内,节点必须等待,不能成为Candidate状态。
-
2、
心跳超时
如下图所示,节点A和C投票给了B,所以节点B是leader节点。节点B会固定间隔时间向两个Follower节点A和C发送心跳消息,这个固定间隔时间被称为heartbeat timeout。Follower节点收到每一条日志信息都需要向Leader节点响应这条日志复制的结果:
5、Log Replication 日志复制
这个概念其实就是怎么让客户端过来的数据同步到所有Follower节点
1、假设接下来客户端发起一个SET 5的请求,这个请求会首先由leader即节点a接收到,并且节点a写入一条日志。由于这条日志还没被其他任何节点接收,所以它的状态是 uncommitted
。
Leader会在下一个心跳中将数据同步给跟随者
2、一旦有大多数节点成功写入这条日志,那么Leader节点的这条日志状态就会更新为committed状态,并且值更新为5。
注意的是:此时Follower节点还是uncommit状态。
3、在接收到Follower的响应后,Leader会通知所有节点提交记录。
4、最后Leader会响应客户端
这种模式就是2PC,这部分衍生出来还有3PC,TCC,SAGA等一致性协议,尤其在分布式事务处理中更为常用。
6、网络分区
1、在发生网络分区的时候,Raft一样能保持一致性。如下图所示,假设我们的集群由5个节点组成,且节点B是Leader节点:
2、我们假设发生了网络分区:节点A和B在一个网络分区,节点C、D和E在另一个网络分区,C,D,E分区就会重新选举
3、如下图所示,且节点B和节点C分别是两个网络分区中的Leader节点:
4、此时两个客户端分别对两个分区进行操作,其中一个客户端将把节点B的值设置为"3",但节点B不能同步大多数,所以他的日志记录仍为未提交
5、另一个客户端将修改 节点C 的值为"8",因为可以同步大多数,所以这个操作能够成功
6、之后再回复分区,节点B将会发现存在"更高领导人",所以将会选择"下台",此时,节点A和节点B将会回滚它们未提交的记录,并同步新领导人的日志
参考文献
1、这个动图非常生动形象:http://raft.taillog.cn/
2、raft论文:https://ramcloud.stanford.edu/wiki/download/attachments/11370504/raft.pdf