以下图片截自
http://thesecretlivesofdata.com/raft/
缘起
当我们服务端只有一个节点的时候,任何数据的改动逻辑都是简单的,当客户端给服务器发消息,只要服务器接收并写下了这条消息,那么该消息就算发送成功
那么当我们服务端有多个节点时,当一条来自客户端的消息到来,应该怎么处理让多个节点达成数据一致呢
此时,raft就登场了
raft工作原理
一个节点可以处于以下三种状态:
- Follower跟随者
- Candidate候选者
- Leader领导者状态
领导者选举
常规流程
最初时,所有节点都以follower的状态开始,每一个节点都有一个随机的选举超时时间(随机的目的是为了让节点之间的选举速度有快有慢,一般在150-300毫秒之间),节点的超时时间一旦走完了,就会成为candidate
如图,每个节点的时钟转速不一样,先转完的人成为candidate
如图,C最快跑完了超时时间,它就转化为candidate
并给自己投一票,同时告诉另外两个节点说:我选举我自己为leader
此时因为AB并没有给其他人投票,自己超时时间也没到,所以就会把票投给了C,并重置自己的超时时间
C获得了大多数的选票,所以它成为了Leader
leader会定期地向follower发送心跳,保证自己的领导地位
follower也必须回复leader的心跳包,证明自己是活跃的
以及循环往复
假设这个时候,leader C挂了
此时AB的超时时间因为不会被重置了,那么先走完超时时间的B成为了leader
注意Term任期增加1
分裂投票
以上情况是理想情况,实际上大多数选举时,几个节点之间可能存在平票的情况,遇到平票时需要再进一轮选举
AB节点,速度一样,同时给自己投了票
C投给了A,D投给了B
此时AB平票,进入新的一轮
日志复制
当选出一位leader后,leader负责将系统的所有变更复制到所有的节点,随着心跳包一起发出
如图,客户端向leader发送了一个set请求
leader将请求复制到follower上
当多数节点成功响应了之后,leader才将set请求缺人,并响应客户端
网络分区时怎么办
当网络产生分区时,如图
分裂产生了两个leader,对于leader C,由于它能得到三票(来自CDE),超过一半的节点,所以C的改动是生效的。而leader B,它只能得到两票(AB),不满足大多数原则,所以它的改动无法生效
当分区恢复时,AB发现C的Term比自己的高,AB都将回滚其未提交的条目,并匹配新领导者的日志