Raft系列2 核心概念(角色&Rules)(原创)

可能是你能找到的最完整最详细的中文版的Raft算法说明博客

内容来源都是原生的论文,可以保证内容的可靠性,并且对论文里面的很多细节做了扩展说明

Role

candidate、follower、leader
role不同,数据结构就不同,遵循的rule也不同

All Server Rules:

  1. 如果RPC里面commitIndex>appliedIndex,则更新appliedIndex。
  • leader角色中,统计超过半数节点copy成功,那么commitIndex就可以增加,增加完之后,就可以apply 命令到状态机中,最后更新appliedIndex
  • Follower角色中,confirm了copy之后,下一个Leader的心跳中会通知更新最新的leaderCommitIndex,然后Follower就会做出对应的调整commitIndex和appliedIndex
  1. 无论任何情况下,当RPC返回的term比自己的大时,不管你是什么身份,都成为follower。
  • 你当前role是leader,你发AppendEntry RPC消息给follower,结果follower返回一个比你大的term,说明你网络不好,已经有新leader了,所以你要转变角色为follower。而新的leader可能是这个follower,也可能是你不知道的其他节点

  • 你当前role是candidate,你发RequestVote RPC消息给follower,结果follower返回一个比你大的term,说明你这轮选举失败了,已经有比你更新的leader了,所以你要转变角色为follower

Followers Rules:

  1. Respond to RPCs from candidates and leaders(收到来自leader或者candidate的RPC消息,要响应)
  2. If election timeout elapses without receiving AppendEntries RPC from current leader or granting vote to candidate:convert to candidate(在一个心跳超时周期内,如果没收到任何消息,则身份成为candidate)

Candidates Rules:

On conversion to candidate, start election:成为candidate要做的事情
• Increment currentTerm
• Vote for self
• Reset election timer
• Send RequestVote RPCs to all other servers

注意第二条描述,candidate只有监听到newLeader的消息才会服从成为follower,加入老leader抽风了一下,被follower发觉,follower发起candidate后但是未成为new leader时,又收到了老leader的心跳,是不服从,直接拒绝的
• If votes received from majority of servers: become leader
• If AppendEntries RPC received from new leader: convert to follower
• If election timeout elapses: start new election

Leader Rules:

  1. 一旦成为leader,第一时间会发一个特殊的心跳给所有的节点,申明地位,阻止小弟们继续选举,并且会发送一个内容为空的log。

  2. leader要定时发送消息给小弟们,即使没有写操作,也要发一个空的心跳消息给小弟们

  3. leader收到客户端的写的操作是,第一时间是自己持久化这个消息,然后把消息RPC给所有follower,超过半数Node添加好了这个消息的时候,就把这个消息的状态标志为applied,并且反馈client操作成功,最后在下一个心跳消息中通知所有的follower 可以applied这个消息了

  4. leader发AppendRPC给follower,如果有的小弟因为日志的序号不对,说明小弟的消息和自己的不一致,有缺失,则更新leader的nextIndex[小弟Index]的值为递减值,重试消息,直到消息完全一致

  5. 一旦选举成功:发一个初始化空日志的AE RPC,并且持续保持心跳
    • If command received from client: append entry to local log,respond after entry applied to state machine (§5.3)
    • If last log index ≥ nextIndex for a follower: sendAppendEntries RPC with log entries starting at nextIndex
    • If successful: update nextIndex and matchIndex forfollower (§5.3)
    • If AppendEntries fails because of log inconsistency:decrement nextIndex and retry (§5.3)

• If there exists an N such that N > commitIndex, a majority of matchIndex[i] ≥ N, and log[N].term == currentTerm:set commitIndex = N (§5.3, §5.4)
这里解决的就是前leader遗留给新leader且未commit的命令
比如 S1有 MS1 MS2 MS3 MS4 MS5命令,commitIndex为3,还有MS4 MS5命令未commit,而且并不知道其它Node是否commit了,所以会发一个空命令的 MS6申明地位,这时候,N=6 >commitIndex=3,最终大家都commit了MS6,那么commitIndex=6

通用Rules

  1. 1个term里,最多只会有一个leader,如果老leader挂了,新leader在这个term选举又失败了,那么可能一个term里没有leader,但是绝对不会出现2个leader

  2. leader-append-only,确保了leader的权威,所有的节点的数据都要保持和leader一样,即使你的log比leader要多,也要服从leader。而且leader不仅不会覆盖自己的log,也不会删除自己的log,所以老leader遗留给新leader的所有的命令都会被commit,不会糟践

  3. 日志比对:如果log Index和log Term一样,那么所有的这样的log的内容是一样的

如果你觉得对你有帮助的话,就给我点赞吧!

你可能感兴趣的:(Raft系列2 核心概念(角色&Rules)(原创))