强烈推荐动画演示:http://thesecretlivesofdata.com/raft/
文字记录:
Raft算法用于实现分布一致性:
- 每个节点有三种状态:Follower,Leader,Candicate
- 每个节点一开始都是
Follower
,当它收不到来自Leader
的心跳消息
就会变成Candicate
,然后给其他节点发送拉票消息
,其他节点收到消息就会返回投票消息
,如果Candicate
收到了超过半数节点的投票消息(当然票数里面会有它自己的一票),他就会变成Leader
了,开始规律地给其他节点发送心跳消息,收到心跳消息的节点就是Follower节点。 - 所有的客户端的对数据的修改消息都会发到Leader节点,并暂不修改数据,而是记录在节点日志中,然后在下一个心跳信息中会包含所有的变更,也就到达了所有的Follower节点,这些节点也先不修改数据,存在节点日志中,随后这些节点发送确认消息给Leader,Leader收到了超过半数的确认消息就提交修改,并给客户端发送相应,并再次告诉Follower自己已经提交了,收到消息的Follower也就提交数据了,这个过程叫
日志复制(Log Replication)
- 再关注一下选举的细节:在Raft中有两个超时设置用于控制选举,一个是
Election Timeout 选举超时
,现在已经知道Leader节点会规律地给Followers发送心跳消息,一段时间
收不到消息,Follower就想要占山为王变成Candicate了,那么这个一段时间到底是多久呢,就是选举超时来控制的。这个选举超时是随机的,在150ms到300ms之间,之所以随机,是因为不希望频繁出现多个节点同时变成Candicate,不是很糟心吗?所以选举超时只对处于Follower状态的节点有用,而且每当收到拉票消息
或者心跳消息
,Follower节点就会重置选举超时为0,重新开始计数。也就保证了,只要Leader活着,Follower就没有造反的机会。当然心跳消息的发送间隔必须小于150ms才能确保这个机制,也就是另一个超时设置:Heartbeat Timaout 心跳超时
,收到心跳消息的节点要返回确认消息给Leader,好让Leader知道自己还活着。 - 虽然选举超时时间是随机的,但是也会有几率使得两个Follower同时变成Candicate,它们会同时给除了自己以外的节点发送拉票消息,要注意,每个投票节点,在一轮选举中,只能投出一票,这里有一个
轮次Term
的概念,每个节点都有这样一个数值,当从Follower突变为Candicate时,该节点会把自己的Term+1,发拉票请求的时候带上Term,供投票方判断它还能不能在此轮次中投票,如果此投票方还没有在此伦次中投过票,它就可以发出投票消息了,当一个节点收到大多数投票变成Leader时,会通过心跳消息统一大家的Term - 当出现网络分区,集群会被分成若干个部分,跟Leader在一起的集群关系不会变化,Leader还是Leader,Follower还是Follower,唯一的问题是发给Leader的消息不一定可以更新成功,要看Leader能联系上的节点加上自身有没有超过半数,如果没有超过半数,暂时就只能放在节点日志中,无法提交
- 其余的分区,节点数量不超过半数的相当于瘫痪了,因为也不会选出新Leader,因为投票数不足。
- 分区节点数量超过半数的,就会自己选出一个新Leader,并且可以正常服务,可以修改数据。这里就有一个问题,新Leader和老Leader的数据就不一致了,客户端在新Leader处修改了数据,再到Leader处获取数据就会出现
stale read
参考阅读:https://pingcap.com/blog-cn/stale-read/
- 解决此问题又要引入Region Leader,不是非常理解细节,不乱说了,再研究研究