Bootstrap

【分布式协议与算法】Raft

协议和算法篇

Raft算法

如何选举领导者?
有哪些成员身份
  • 领导者:处理写请求,管理日志复制,不断发送心跳信息
  • 跟随者:接受和处理来自领导者的消息,领导者心跳超时,会主动推荐自己当候选人
  • 候选人:向其他节点发送请求投票RPC消息,通知其他节点来投票,如果赢得大多数选票,晋升为领导者
选举领导者的过程

1.初始状态,所有节点都是跟随者状态。Raft算法实现了随机超时时间的特性,每个节点等待领导者节点心跳信息的超时时间间隔是随机的。
在这里插入图片描述

2.上图的A因为超时时间最短,会最先变成候选人,发起投票(先给自己投票,再给其他节点发送投票消息)
在这里插入图片描述

3.如果其他节点接收到A的请求投票消息,在编号为1的任期中,还没有进行过投票,它将把投票给节点A,并增加自己的任期编号
在这里插入图片描述

4.如果候选人在选举超时时间内赢得了大多数选票,就会成为本届任期内新的领导者
在这里插入图片描述

5.A当选领导者后,将周期性地发送心跳消息,通知其他服务器我是领导者,阻止跟随者发起新的选举
在这里插入图片描述

选举过程四连问
节点间如何通讯

领导者选举中,通常需要用到两类RPC:
1.请求投票RPC,是由候选人在选举期间发起,通知各节点进行投票
2.日志复制RPC,是由领导者发起,用于复制日志和提供心跳信息

什么是任期

1.跟随者在等待领导者心跳信息超时后,推举自己成为候选人时,会增加自己的任期号
2.如果一个服务器节点,发现自己的任期编号比其他节点小,那么他会更新自己的编号到较大的编号值
3.如果一个候选者或者领导者,发现自己的任期编号比其他节点小,那么他会立即恢复成跟随者状态
4.如果一个节点接收到一个包含较小任期编号的请求,那么他会直接拒绝这个请求

选举有哪些规则

1.领导者周期性地向所有跟随者发送心跳消息,通知大家我是领导者
2.如果在指定时间内,跟随者没有接收到来自领导者的消息,那么他会认为当前没有领导者,推举自己为候选人,发起领导者选举
3.在一次选举中,赢得大多数选票的候选人,将晋升为领导者
4.在一个任期内,领导者一直都会是领导者,直到他自身出现问题(宕机),或者因为网络延迟,其他节点发起一轮新的选举
5.在一次选举中,每一个服务器节点最多会对一个任期编号透出一张选票,并按照“先来先服务”的原则进行投票
6.当任期编号相同时,日志完整性高的跟随者,拒绝投票给日志完整性低的候选人

随机超时时间又是什么

Raft算法巧妙地使用随机选举超时时间,将超时时间都分散开来,在大多数情况下只有一个服务器节点先发起选举
1.跟随者等待领导者心跳信息超时的时间间隔是随机的
2.当没有候选人赢得过半票数,选举无效了,这时需要等待一个随机时间间隔,也即等待选举超时的时间间隔是随机的

内容小结

1.Raft中,只有日志最完整的节点才能当领导者,并且日志必须是连续的
2.通过任期,领导者心跳信息,随机选举超时时间,大多数选票原则等,保证了一个任期只有一位领导

日志复制

如何理解日志

日志是一种数据格式,包含:指令,任期编号,索引值

  • 指令:一条由客户端指定的,状态机需要执行的指令
  • 索引值:日志项对应的整数索引值,是一个连续的,单调递增的整数号码
  • 任期编号:创建这条日志项的领导者的任期编号
如何复制日志

在这里插入图片描述

1.接收到客户端请求后,领导者基于客户端请求中的指令,创建一个新日志项,并附加到本地日志
2.领导者通过日志复制RPC ,将新的日志项复制到其他的服务器
3.当领导者将日志项成功复制到大多数的服务器上的时候,领导者会将这条日志项提交给它的状态机中
4.领导者将执行的结果返回给客户端
5.当跟随者接收到心跳信息,或者新的日志复制RPC 消息后,如果跟随者发现领导者已经提交了某条日志项,而他还没有提交,那么跟随者就将这条日志项提交到本地的状态机中

如何实现日志的一致

领导者通过日志复制RPC 的一致性检查,找到跟随者节点上,与自己相同日志项的最大索引值。此时,这个索引值之前的日志,领导者和跟随者是一致的,之后的日志是不一致的。
然后,领导者强制跟随者更新覆盖的不一致日志项,实现日志的一致。
如下图,当前是要复制索引为8的日志,但是找不到索引为7,任期为4的日志,继续往前面找。找到了索引为6,任期为3的日志。那么这个日志项之前的日志是和领导者一致的,直接用领导者的日志覆盖后面的7,8
在这里插入图片描述

内容小结

1.副本数据以日志的形式存在,日志项中的指令表示用户指定的数据
2.multi-paxos不要求日志是连续的,但在Raft 中日志必须是连续的。日志的完整性最高的节点才能当选领导者
3.值的共识和日志的一致都是由领导者决定的

成员变更

成员变更的问题

问题:可能会出现两个领导者
解决方法:单节点变更
异常情况:在领导者启动时,创建一个NO_OP日志项,只有当领导者将NO_OP日志项提交后,再执行成员变更请求。

内容小结

1.成员变更的问题,主要在于进行成员变更时,可能存在新旧配置的2个“大多数”,导致集群中同时出现两个领导者,破坏了Raft的领导者的唯一性原则,影响了集群的稳定运行
2.单节点变更是利用“一次变更一个节点,不会同时存在旧配置和新配置2个‘大多数’”的特性,实现成员变更(etcd,hashicorp raft)
3.一般需要根据场景特点,在一致性强度和实现复杂度之间进行权衡

;