Raft精华

基础

Raft是管理复制日志的一致性算法
Raft基于Leader,Follow
各个机器上,日志一致了,状态就一致了
客户端只许和Leader节点交互,
Follower节点只许从Leader节点接收写日志
Leader节点向Follower节点写日志,只有一半的节点写成功了,才返回客户端成功。
Leader定期向Follower节点发送心跳包,告诉它们正常

选主

如果之前的Leader工作不正常,将结束当前Term,开始选举
Follower将自己变成选举状态,它先投自己一票,然后向其它follower拉票
Follower等待结果

  1. 赢得选举,告诉其它Follower
  2. 别人赢得选举,变成Follower,别人赢得选举就是收到term_id大于自己的current_term_id且声称自己为leader的requestRpc请求
  3. 没选出来,所有候选人都超时,继续选,term_id加1
    得票过半当选,得票是先到先得,每个节点只能投给一个候选人
    等待选票过程中,如果别人的心跳包中,term大于自己的term,就变成follower,听从新上任Leader指挥
    为了避免长时间选不出leader,每个follower发现leader不可用的超时时间是一个随机数,避免同时发现Leader不可用。
    每个候选人下一轮拉票请求的时间间隔也是个随机数,避免同时拉票

leader选出来就可以接收客户端请求了

记日志

每条日志有序号log index
日志要记操作,还要记term
日志在半数follower上记了,leader才能commit
leader要告诉follow term以及前次index,这样follower才能知道自己是不是漏记了,如果漏记了会全补上
需要有一种机制来让leader和follower对log达成一致,leader会为每个follower维护一个nextIndex,表示leader给各个follower发送的下一条log entry在log中的index,初始化为leader的最后一条log entry的下一个位置。leader给follower发送AppendEntriesRPC消息,带着(term_id, (nextIndex-1)), term_id即(nextIndex-1)这个槽位的log entry的term_id,follower接收到AppendEntriesRPC后,会从自己的log中找是不是存在这样的log entry,如果不存在,就给leader回复拒绝消息,然后leader则将nextIndex减1,再重复,知道AppendEntriesRPC消息被接收。

以leader和b为例:

初始化,nextIndex为11,leader给b发送AppendEntriesRPC(6,10),b在自己log的10号槽位中没有找到term_id为6的log entry。则给leader回应一个拒绝消息。接着,leader将nextIndex减一,变成10,然后给b发送AppendEntriesRPC(6, 9),b在自己log的9号槽位中同样没有找到term_id为6的log entry。循环下去,直到leader发送了AppendEntriesRPC(4,4),b在自己log的槽位4中找到了term_id为4的log entry。接收了消息。随后,leader就可以从槽位5开始给b推送日志了。

Raft精华_第1张图片
image.png

Leader负责一致性检查,同时让所有的Follower都和自己保持一致
Raft对选举有限制条件1:Candidate在拉票时需要携带自己本地已经持久化的最新的日志信息,等待投票的节点如果发现自己本地的日志信息比竞选的Candidate更新,则拒绝给他投票。
Raft对选举有 限制条件2:只允许Leader提交(commit)当前Term的日志。
更详细见https://zhuanlan.zhihu.com/p/27207160

你可能感兴趣的:(Raft精华)