以下图片截自 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都将回滚其未提交的条目,并匹配新领导者的日志