Raft算法

一、Raft算法概述

1.Raft算法是从leader选举,日志同步,安全性,日志压缩等方面进行考虑解决问题

2.流程

   1.leader   接受客户端请求,向followers发送日志同步请求,当绝大部分followers都接收到同步请求时候,告诉followers提交日志

   2.followers  接受并持久化Leader同步的日志,在Leader告之日志可以提交之后,提交日志

  3.Candidate:Leader选举过程中的临时角色

3.follower只接受其他服务器的请求,当因为超时等原因,follower未接收到leader的同步请求时候,它会成为一个Candidate  会发起leader选举,到大多数服务器投票的Candidate会成为新的Leader。Leader在宕机之前会一直保持Leader的状态

二、Leader选举

1.Raft 使用心跳(heartbeat)触发Leader选举,服务初始时候,为follower。当leader发送心跳检测,当follower在超贵心跳检测时间未收到心跳,follower会将其term加一成为Candidate 这时候会发起一次leader选举请求,

     1.当绝大多数都同意,则成为新的leader。

     2.收到了leader的消息,表示其他服务已经成为leader

    3.没有服务器赢得多数的选票,Leader选举失败,等待选举时间超时后发起下一次选举

2.选举出Leader后,Leader通过定期向所有Followers发送心跳信息维持其统治。若Follower一段时间未收到Leader的心跳则认为Leader可能已经挂了,再次发起Leader选举过程。

Raft保证选举出的Leader上一定具有最新的已提交的日志,这一点将在四、安全性中说明

三、日志同步

1.leader选举出来后,会接受客户端的请求,leader将请求作为日志条目添加到他的日志中,并向follower发送APPendEntis RPC请求进行同步复制日志条目,当绝大多数服务器接收到日志后,leader会将这条日志应用到自己的状态机,并返回给客户端结果,

2.某些follower可能没有收到同步日志,leader会一直发送同步请求,知道follower接收到同步日志

3.日志由有序编号(log index)的日志条目组成。每个日志条目包含它被创建时的任期号(term),和用于状态机执行的命令。如果一个日志条目被复制到大多数服务器上,就被认为可以提交(commit)了。

Raft日志同步保障一下两点

1.如果不同日志中有两条日志的索引和任期好相同,则认为是同一条日志,所以他们的存储的命令是相同的

2,如果不同日志中有两条日志的索引和任期好相同,和他们以前的所有日志也是相同的

第一条特性源于Leader在一个term内在给定的一个log index最多创建一条日志条目,同时该条目在日志中的位置也从来不会改变。

第二条特性源于 AppendEntries 的一个简单的一致性检查。当发送一个 AppendEntries RPC 时,Leader会把新日志条目紧接着之前的条目的log index和term都包含在里面。如果Follower没有在它的日志中找到log index和term都相同的日志,它就会拒绝新的日志条目。

一般情况下,Leader和Followers的日志保持一致,因此 AppendEntries 一致性检查通常不会失败。然而,Leader崩溃可能会导致日志不一致:旧的Leader可能没有完全复制完日志中的所有条目。

上图阐述了一些Followers可能和新的Leader日志不同的情况。一个Follower可能会丢失掉Leader上的一些条目,也有可能包含一些Leader没有的条目,也有可能两者都会发生。丢失的或者多出来的条目可能会持续多个任期。

Leader通过强制Followers复制它的日志来处理日志的不一致,Followers上的不一致的日志会被Leader的日志覆盖。

Leader为了使Followers的日志同自己的一致,Leader需要找到Followers同它的日志一致的地方,然后覆盖Followers在该位置之后的条目。

Leader会从后往前试,每次AppendEntries失败后尝试前一个日志条目,直到成功找到每个Follower的日志一致位点,然后向后逐条覆盖Followers在该位置之后的条目。

四、安全性

1.拥有最新调教的日志log的follower才能成为leader

Candidate在发送leader选举时候,要带上自己的最后一条日志的term和index 当其他服务器接收到请求后,如果发现自己的term和index大于Candidate的,则拒绝投票,如果本地的最后一条log entry的term更大,则term大的更新,如果term一样大,则log index更大的更新。

Leader只能推进commit index来提交当前term的已经复制到大多数服务器上的日志,旧term日志的提交要等到提交当前term的日志来间接提交(log index 小于 commit index的日志被间接提交)

在阶段a,term为2,S1是Leader,且S1写入日志(term, index)为(2, 2),并且日志被同步写入了S2;

在阶段b,S1离线,触发一次新的选主,此时S5被选为新的Leader,此时系统term为3,且写入了日志(term, index)为(3, 2);

S5尚未将日志推送到Followers就离线了,进而触发了一次新的选主,而之前离线的S1经过重新上线后被选中变成Leader,此时系统term为4,此时S1会将自己的日志同步到Followers,按照上图就是将日志(2, 2)同步到了S3,而此时由于该日志已经被同步到了多数节点(S1, S2, S3),因此,此时日志(2,2)可以被提交了。;

在阶段d,S1又下线了,触发一次选主,而S5有可能被选为新的Leader(这是因为S5可以满足作为主的一切条件:1. term = 5 > 4,2. 最新的日志为(3,2),比大多数节点(如S2/S3/S4的日志都新),然后S5会将自己的日志更新到Followers,于是S2、S3中已经被提交的日志(2,2)被截断了。

增加上述限制后,即使日志(2,2)已经被大多数节点(S1、S2、S3)确认了,但是它不能被提交,因为它是来自之前term(2)的日志,直到S1在当前term(4)产生的日志(4, 4)被大多数Followers确认,S1方可提交日志(4,4)这条日志,当然,根据Raft定义,(4,4)之前的所有日志也会被提交。此时即使S1再下线,重新选主时S5不可能成为Leader,因为它没有包含大多数节点已经拥有的日志(4,4)。

五、日志压缩

在实际的系统中,不能让日志无限增长,否则系统重启时需要花很长的时间进行回放,从而影响可用性。Raft采用对整个系统进行snapshot来解决,snapshot之前的日志都可以丢弃。

每个副本独立的对自己的系统状态进行snapshot,并且只能对已经提交的日志记录进行snapshot。

Snapshot中包含以下内容:

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

当Leader要发给某个日志落后太多的Follower的log entry被丢弃,Leader会将snapshot发给Follower。或者当新加进一台机器时,也会发送snapshot给它。发送snapshot使用InstalledSnapshot RPC(RPC细节参见八、Raft算法总结)。

做snapshot既不要做的太频繁,否则消耗磁盘带宽, 也不要做的太不频繁,否则一旦节点重启需要回放大量日志,影响可用性。推荐当日志达到某个固定的大小做一次snapshot。

做一次snapshot可能耗时过长,会影响正常日志同步。可以通过使用copy-on-write技术避免snapshot过程影响正常日志同步。

六、Raft与Multi-Paxos的异同

Raft与Multi-Paxos都是基于领导者的一致性算法,乍一看有很多地方相同,下面总结一下Raft与Multi-Paxos的异同。

Raft与Multi-Paxos中相似的概念:

Raft与Multi-Paxos的不同:

七、成员变更

 

Cold: 旧集群的节点配置信息,eg 【node1, node2, node3】
Cnew:新集群的节点配置信息, eg 【node1, node2, node3, node4, node5】
Cold_new:新旧节点配置信息都包含。

T1-T2阶段可能选举出Cold节点,也可能选举出Cold_new节点的,选举成功的条件是Cold和Cnew中的大多数节点都同意,也就意味着他选举成功,Cold中就不会有别的candidate被选举成功,所以不会出现两个leader

T2-T3阶段,只能是Cold_Cnew,因为T2阶段Cold_new已经复制成功,表明Cold和Cold_new的日志已经同步大部分,所以选举出来的,如果选举leader成功,必须要一个拥有Cold_new日志的follower,然而该follower更新,他必然会拒绝该请求, 而只会批准哪些拥有Cold_new日志的Candidate.

T3-T4阶段,选举出来的可能是Cold_new也可能是new的,如果是Cold_new,则必须new也有大部分同意,反过来说,如果new节点集群选了一个拥有Cnew配置的节点,那么Cold_new在new节点集群中必然没法得到多数同意, 因此可以看出不会同时存在两个leader

T4之后,再选leader一定是选择拥有Cnew配置的candidate. 因为假设一个拥有Cold_new的节点申请大家的投票,需要Cnew中的大部分节点同意,但是Cnew中的大部分人都已经写入了日志Cnew,所以他们不会同意Cold_new节点成为leader.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值