Raft算法学习

持续更新中,先填一点交个作业,我一定会回来完善的。

经典动画 [http://thesecretlivesofdata.com/raft/](http://thesecretlivesofdata.com/raft/)

相对于Paxos,Raft最大的特点就是易于理解,为了达到这个目标,Raft主要做了两个方面的事情:

  1. 问题分解:把共识算法分解为三个子问题,分别是领导者选举、日志复制、安全性问题
  2. 状态简化:对算法做出一些限制,减少状态数量和可能产生的变动。(每一个节点都处于Leader、Follower、Candidate三个状态之一;节点之间通过RPC通信。主要有两种RPC,RequestVoteRPC请求投票,AppendEntries追加条目)

复制状态机
模型一句话描述就是:多个节点上,从相同的初始状态开始,执行相同的一串命令,产生相同的最终状态。
相同的初始状态+相同的输入(且相同顺序)= 相同的结束状态
在这里插入图片描述
可以说,我们使用raft等共识算法,就是为了实现复制状态机,而保证一致性。

Raft 协议的易理解性描述

这里我就一种极简思维来描述和概念验证下 Raft 协议的工作方式。

在一个由 Raft 协议组织的集群中有三类角色:

  • Leader(领袖)
  • Follower(群众)
  • Candidate(候选人)

就像一个民主社会,领袖由民众投票选出。刚开始没有领袖,所有集群中的参与者都是群众,那么首先开启一轮大选,在大选期间所有群众都能参与竞选,这时所有群众的角色就变成了候选人,民主投票选出领袖后就开始了这届领袖的任期,然后选举结束,所有除领袖的候选人又变回群众角色服从领袖领导。这里提到一个概念「任期」,用术语 Term 表达。关于 Raft 协议的核心概念和术语就这么多而且和现实民主制度非常匹配,所以很容易理解。三类角色的变迁图如下,结合后面的选举过程来看很容易理解。

一、Leader 选举过程

领导者选举过程非常简单,但是细节很多。
在这里插入图片描述
如果其他节点接收到候选人 A 的请求投票 RPC 消息,在编号为 1 的这届任期内,也还没有 进行过投票,那么它将把选票投给节点 A,并增加自己的任期编号。
在这里插入图片描述
如果候选人在选举超时时间内赢得了大多数的选票,那么它就会成为本届任期内新的领导者
在这里插入图片描述
节点 A 当选领导者后,他将周期性地发送心跳消息,通知其他服务器我是领导者,阻止跟 随者发起新的选举,篡权。
在这里插入图片描述
细节问题:

  • 节点间是如何通讯的呢?
    请求投票(RequestVote)RPC,是由候选人在选举期间发起,通知各节点进行投票;
    日志复制(AppendEntries)RPC,是由领导者发起,用来复制日志和提供心跳消息。
    日志复制 RPC 只能由领导者发起,这是实现强领导者模型的关键之一,后续能更好地理解日志复制,理解日志的一致是怎么实现的。

  • 什么是任期呢?
    每一个任期内只能有一个领导者。

  • 选举有哪些规则?
    跟随着在每一个任期内只能给一个候选者投票。
    领导者周期性地向所有跟随者发送心跳消息(即不包含日志项的日志复制 RPC 消息), 通知大家我是领导者,阻止跟随者发起新的选举。
    如果在指定时间内,跟随者没有接收到来自领导者的消息,那么它就认为当前没有领导者,推举自己为候选人,发起领导者选举。
    在一次选举中,赢得大多数选票的候选人,将晋升为领导者。
    在一个任期内,领导者一直都会是领导者,直到它自身出现问题(比如宕机),或者因为网络延迟,其他节点发起一轮新的选举。
    在一次选举中,每一个服务器节点多会对一个任期编号投出一张选票,并且按照“先 来先服务”的原则进行投票。比如节点 C 的任期编号为 3,先收到了 1 个包含任期编号 为 4 的投票请求(来自节点 A),然后又收到了 1 个包含任期编号为 4 的投票请求(来 自节点 B)。那么节点 C 将会把唯一一张选票投给节点 A,当再收到节点 B 的投票请求 RPC 消息时,对于编号为 4 的任期,已没有选票可投了。

  • 随机超时时间又是什么?
    跟随者等待领导者心跳信息超时的时间间隔,是随机的。
    当没有候选人赢得过半票数,选举无效了,这时需要等待一个随机时间间隔,也就是 说,等待选举超时的时间间隔,是随机的。

二、日志复制

可以把 Raft 的日志复制理解成一个优化后的二阶段提交(将二阶段优化成了一阶段), 减少了一半的往返消息,也就是降低了一半的消息延迟。那日志复制的具体过程是什么呢?

首先,领导者进入第一阶段,通过日志复制(AppendEntries)RPC 消息,将日志项复制 到集群其他节点上。
接着,如果领导者接收到大多数的“复制成功”响应后,它将日志项提交到它的状态机,并 返回成功给客户端。如果领导者没有接收到大多数的“复制成功”响应,那么就返回错误给 客户端。
领导者将日志项提交到它的状态机,怎么没通知跟 随者提交日志项呢?
这是 Raft 中的一个优化,领导者不直接发送消息通知其他节点提交指定日志项。因为领导 者的日志复制 RPC 消息或心跳消息,包含了当前最大的,将会被提交的日志项索引值。所 以通过日志复制 RPC 消息或心跳消息,跟随者就可以知道领导者的日志提交位置信息。
因此,当其他节点接受领导者的心跳消息,或者新的日志复制 RPC 消息后,就会将这条日 志项提交到它的状态机。而这个优化,降低了处理客户端请求的延迟,将二阶段提交优化为 了一段提交,降低了一半的消息延迟。

再走一遍这个过程,这样可以更加全面地掌 握日志复制。
接收到客户端请求后,领导者基于客户端请求中的指令,创建一个新日志项,并附加到 本地日志中。
在这里插入图片描述
流程

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

总结

就引用 Raft 论文最后的一节的综述来总结本文吧。

算法以正确性、高效性、简洁性作为主要设计目标。
虽然这些都是很有价值的目标,但这些目标都不会达成直到开发者写出一个可用的实现。
所以我们相信可理解性同样重要。

深以为然,想想 Paxos 算法是 Leslie Lamport 在 1990 年就公开发表在了自己的网站上,想想我们是什么时候才听说的?什么时候才有一个可用的实现?而 Raft 算法是 2013 年发表的,大家在参考[5]上面可以看到有多少个不同语言开源的实现库了,这就是可理解性的重要性。

参考:

http://www.cnblogs.com/mindwind/p/5231986.html
https://blog.51cto.com/u_15469906/5135025
http://blog.csdn.net/dc_726/article/details/48832405

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值