Raft算法——NWU_LK

Raft算法

raft算法会先选举出leader,leader完全负责replicated log的管理。leader负责接受所有客户端更新请求,然后复制到follower节点,并在“安全”的时候执行这些请求。如果leader故障,followes会重新选举出新的leader。 这就涉及到raft最新的两个子问题: leader election和log replication。

一. raft中的角色

Raft将系统中的角色分为领导者(Leader)、跟从者(Follower)和候选者(Candidate):

  • Leader:接受客户端请求,并向Follower同步请求日志,当日志同步到大多数节点上后告诉Follower提交日志。
  • Follower:接受并持久化Leader同步的日志,在Leader告之日志可以提交之后,提交日志。
  • Candidate:Leader选举过程中的临时角色。
    left
    Raft要求系统在任意时刻最多只有一个Leader,正常工作期间只有Leader和Followers。Raft算法将时间分为一个个的任期(term),任期用连续的数字进行表示。每一个term的开始都是Leader选举,一个或多个候选人会试图成为领导人。在成功选举Leader之后,Leader会在整个term内管理整个集群。在某些情况下,选票会被瓜分,有可能没有选出领导人,该term就会因为没有Leader而结束。那么,将会开始另一个任期,并且立刻开始下一次选举。Raft 算法保证在给定的一个任期最多只有一个领导人。
二. Leader选举

Raft 使用心跳(heartbeat)触发Leader选举。当服务器启动时,初始化为Follower。每一个follower都有一个时钟,是一个随机的值,表示的是follower等待成为leader的时间,谁的时钟先跑完,则发起leader选举。

初始化: 刚开始所有的节点都为follower,当某个节点的时钟走完后,该节点成为Candidate。首先会给自己投一票,并且会给其他的节点发送RequestVote RPC,让其给自己投票。因为RequestVote RPC有一定的时间间隔,如果其他节点在未收到RequestVote RPC之前将自己的时钟走完,那么该节点也成为Candidate,其也会向其他非候选节点发出RequestVote RPC让给自己投票,但是最终是得票数最多的节点成为主节点。(一个节点只有一票,若候选节点的票数相同就重新投票)

正常运行: 在集群正常运行的过程中,主节点会持续不断的给follower发送AppendEntries RPC(一种心跳机制),该时间间隔一定小于从节点的设置的时钟倒计时。当从节点收到了主节点的AppendEntries RPC之后就会重置时钟到最大值,然后重新开始倒计时,这样就保证了从节点不会在主节点正常工作时发起选举的请求。

主节点挂掉: 主节点挂掉后,从节点一直没收到主节点发来的AppendEntries RPC,当某个follower走完了时钟也没有收到AppendEntries RPC时,该从节点会变为候选节点,然后给自己投一票后,发送RequestVote RPC到其余的follower节点,让他们给自己投票,此时的这个过程就相当于初始化选举主节点的过程,选票最多的那个节点会变为主节点,而挂掉的主节点重新启动时会变为从节点,并且时钟也会倒计时。

Leader选举的限制:
在Raft协议中,所有的日志条目都只会从Leader节点往Follower节点写入,且Leader节点上的日志只会增加,绝对不会删除或者覆盖。这意味着Leader节点必须包含所有已经提交的日志,即能被选举为Leader的节点一定需要包含所有的已经提交的日志。因为日志只会从Leader向Follower传输,所以如果被选举出的Leader缺少已经Commit的日志,那么这些已经提交的日志就会丢失,显然这是不符合要求的。

三. 日志复制

日志的组成

日志由有序编号(log index)的日志条目(log entries)组成。每个日志条目包含它被创建时的任期号(term)和用于状态机执行的命令。如果一个日志条目被复制到大多数服务器上,就被认为可以提交(commit)了。
在这里插入图片描述
上图显示,共有 8 条日志,提交了 7 条。提交的日志都将通过状态机持久化到磁盘中,防止宕机。

日志复制的流程

Leader选出后,就开始接收客户端的请求。Leader把请求作为日志条目(Log entries)加入到它的日志中,然后并行的向其他服务器发起 AppendEntries RPC(该请求也是主节点检测从节点心跳的请求)复制日志条目。然后从节点会复制这个日志到各自的服务器上,然后会给主节点返回结果。当主节点收到大部分从节点已经复制完成的响应后,Leader将这条日志应用到它的状态机并向客户端返回执行结果。之后再下一次主节点给从节点发送AppendEntries RPC时,从节点也会将该日志应用到各自的状态机上。如果期间follower 宕机或者运行缓慢或者丢包,主节点未收到大部分节点的响应,那么该日志就不会被应用到状态机,leader会不断的重试,直到follower重新启动,并且大多数的 follower 最终都复制了所有的日志条目后,主节点会将日志应用到状态机。此时,又有follower节点启动了,那么主节点发来的AppendEntries RPC会让该从节点复制数据,并且直接将数据应用到其状态机(一个AppendEntries RPC会让从节点补一条记录,并应用到状态机)。

特点
通过对以上流程的分析,可以得到以下两个基本特点

  1. 如果不同节点的日志中的两个条目有着相同的索引和任期号,则它们所存储的命令是相同的
  2. 如果不同节点的日志中的两个条目有着相同的索引和任期号,则它们之前的所有条目都是完全一样的

日志不正常的情况

  1. 一个Follower可能会丢失掉Leader上的一些条目。以上已经分析过,比如主节点加入日志后,从节点宕机的话,那么会使从节点丢掉条目

  2. Follower也有可能包含一些Leader没有的条目。

    丢失的或者多出来的条目可能会持续多个任期。

保证日志的正常复制

Leader通过强制Followers复制它的日志来处理日志的不一致,Followers上的不一致的日志会被Leader的日志覆盖。Leader为了使Followers的日志同自己的一致,Leader需要找到Followers同它的日志一致的地方,然后覆盖Followers在该位置之后的条目。
具体的操作是:Leader会从后往前试,每次AppendEntries失败后尝试前一个日志条目,直到成功找到每个Follower的日志一致位置点(基于上述的两条保证),然后向后逐条覆盖Followers在该位置之后的条目。

四. 安全性
  1. 拥有最新的已提交的log entry的Follower才有资格成为leader
  2. Leader只能推进commit index来提交当前term的已经复制到大多数服务器上的日志
五. 日志压缩

在实际的系统中,不能让日志无限增长,否则系统重启时需要花很长的时间进行回放,从而影响可用性。Raft采用对整个系统进行snapshot来解决,snapshot之前的日志都可以丢弃(以前的数据已经落盘了)。每个节点独立的对自己的系统状态进行snapshot,并且只能对已经提交的日志记录进行snapshot。

Snapshot介绍

包括以下两个信息

  1. 日志元数据,最后一条已提交的 log entry的 log index和term。这两个值在snapshot之后的第一条log entry的AppendEntries RPC的完整性检查的时候会被用上。
  2. 系统当前状态。

当Leader要发给某个日志落后太多的Follower的log entry被丢弃,Leader会将snapshot发给Follower。或者当新加进一台机器时,也会发送snapshot给它。发送snapshot使用InstalledSnapshot RPC。做snapshot既不要做的太频繁,否则消耗磁盘带宽, 也不要做的太不频繁,否则一旦节点重启需要回放大量日志,影响可用性。推荐当日志达到某个固定的大小做一次snapshot。做一次snapshot可能耗时过长,会影响正常日志同步。可以通过使用copy-on-write技术避免snapshot过程影响正常日志同步。

六. 成员变更

成员变更请求被当成普通的写请求,由领导者得到多数节点响应后,每个节点提交成员变更日志,将从旧成员配置(Cold)切换到新成员配置(Cnew)。但每个节点提交成员变更日志的时刻可能不同,这将造成各个服务器切换配置的时刻也不同,这就有可能选出两个领导者,破坏安全性。

考虑以下这种情况:集群配额从 3 台机器变成了 5 台,可能存在这样的一个时间点,两个不同的领导者在同一个任期里都可以被选举成功(双主问题),一个是通过旧的配置,一个通过新的配置。简而言之,成员变更存在的问题是增加或者减少的成员太多了,导致旧成员组和新成员组没有交集,因此出现了双主。

因此为了解决双主问题,Raft解决方法是每次成员变更只允许增加或删除一个成员(如果要变更多个成员,连续变更多次)。

七. 动画理解raft算法

多看多试几遍就能理解raft算法了——raft动画演示地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值