分布式一致性算法Raft

145 阅读5分钟

“我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第1篇文章,点击查看活动详情

开始聊一聊简易流程:

Raft是一个强一致性算法,client向leader发送一个命令,leader开始更新日志,并向follower发送更新日志的命令,当得到大多数follower的回复时,leader可以向client回复ack,在下一次发送心跳的时候就可以附加上自己日志索引,follower收到可以将之前的log提交到状态机中。

分析

状态的最终一致状态立即一致 让跨网络的机器协调一致的工作

组织机器状态最终一致并允许局部性失败的算法叫做分布式一致性算法,一致性算法的目标就是保证集群上所有节点的状态一致,主要是在读写请求上需要副节点高度一致,leader必须将指令同步给所有follower,在理想状态下,我们期望任意节点发生写命令都会立即的在其他节点上变更状态,这其中没有任何时延,所有节点都好像是单机—样被变更状态。

网络延迟要远远慢于内存操作,写入命令不可能被同时执行,因此如果在不同节点发生不同的写命令,那么在其他节点上这些写命令被应用的顺序很可能完全不同。所以需要leader和follower发生很多通信来保持高度一致,这些通信延时可能会很长、很复杂,但是也有rpc的超时功能在为此功能再加一层保护。

如果我们不要求所有节点的写命令立即被执行,而仅仅是保证所有的写命令在所有的节点上按同样的顺序最终被执行呢?第一,仅仅允许一个节点处理写命令,第二,所有的节点维护一份顺序一致的日志。

image.png

方案:初始化的时候有一个leader节点,负责发送日志给follower,日志顺序一致。当发送Read请求时,任意节点都可以回复读请求,而Write请求只能发送给主节点。leader先写入日志,然后同步给其他follower节点,当有半数follower节点回复,leader就提交日志表示成功。日志顺序是leader,然后同步到状态机,其他follower应用到状态机。raft最终会强制让这些⽇志变得⼀模⼀样。这其中可能存在短暂的差异,但在长时间的运行,所有的⽇志都会被leader所修改,直到leader确信它们都⼀样位置,只有这个时候,leader才会去执⾏它们。当leader崩溃的时候,其他follower通过pingpong心跳感知leader是否无响应,然后开始选举新的leader继续执行。(此处如果不理解可以看一下MIT官方课程网站提供的动画)

其中的细节

1、 为了防止split brain,提出了在一个任期内必须获得半数以上的票数才能当选,并且机器数必须为奇数,可以避免一半机器的宕机所产生的问题

2、 投票:candidate发起投票RPC到follower或者candidate,在任何给定的term中,每台服务器只能给⼀个candidate投票,不能让两个candidate都拿到绝⼤多数投票

3、 每个节点上的状态机按照自己的节奏,逐条应用日志上的写命令来变更状态。

4、 请求的参数:候选人的任期号,请求选片的候选人的id号,候选人最后日志条目的索引值,候选人最后日志条目的任期号(因为不会发送给任期号比自己小的候选人,只会发送给日志比自己新,任期号更高的候选人)。

特性

选举安全特性:对于一个给定的任期号,最多只能由一个leader被选举出来,防止split brain

领导人只附加原则:领导人绝对不会删除或者覆盖自己的日志,只会增加

日志匹配原则:如果两个日志在相同的索引位置的日志任期号相同,则我们认为这个日志从头到这里全部相同

领导人完全特性:如果某个日志在某个任期号已经提交,那么这个日志条目一定出现在更新的所有领导人中

状态机安全特性:如果一个leader已经给定索引值位置的日志条目应用到状态机中,那么其他的任何服务器在这个索引位置就只用这个日志。

(独特的特性)

  • 强领导者:和其他一致性算法相比,Raft 使用一种更强的领导能力形式。比如,日志条目只从领导者发送给其他的服务器。这种方式简化了对复制日志的管理并且使得 Raft 算法更加易于理解。
  • 领导选举:Raft 算法使用一个随机计时器来选举领导者。这种方式只是在任何一致性算法都必须实现的心跳机制上增加了一点机制。在解决冲突的时候会更加简单快捷。
  • 关系调整:Raft 使用一种共同一致的方法来处理集群成员变换的问题,在这种方法中,两种不同的配置都要求的大多数机器会重叠。这就使得集群在成员变换的时候依然可以继续工作。