您的位置:首页 > 其它

raft论文阅读摘要

2016-06-04 11:08 218 查看

raft论文阅读摘要

本文只是基本摘要,只能作为论文的辅助理解,要想真正弄懂raft还是得自己看论文,别人的理解和原文的意思总是有出入的,而且翻译的文章不可能完全符合英文本来的含义

基础构架



本质上raft是对Replicated state machine进行同步的算法。为了提高可用性,由client发来的命令需要被复制到多个server节点上,raft解决的就是如何在网络分区,节点故障的情况下保证这个复制的过程安全可靠的进行,使这些状态机保持一致的状态。

基本概念

server的状态:



1. leader:负责接受client的命令并完成复制过程。

2. follower:被动的接受leader复制请求,在选举过程参与投票工作

3. candidate:由follower转变,leader失效后作为竞选者参与leader竞选

在正常情况下,raft由leader和follower构成,leader失效后才会出现candidate,server之间以RPC的方式进行通信

log



server将接受到的消息以log的形式进行存放,每个消息就是log中的一个entry,每个entry包括一个term号和log index和client发来的命令(比如x<-0)。raft保证committee后相同的log index位置的entry都是一致的。

Term



raft将时间分为任意长度的时间段,称之为term,每个term由一个选举过程开始,接下来是正常的复制过程(如果选举过程成功选出了leader,不然开始另一个新的term),节点之间的消息会附上term号以区别那些过期的消息。

committee

当leader发现client的命令由leader复制到了多数节点,可以认为这条消息已经安全可靠,可以保证其最终复制到所有的节点上,所以leader会向那些follower发出committee并向client回复复制过程完成,收到committee的follower可以启用entry中的命令,同时raft的规则保证,发出committee后,所有在那个被committeeed的entry之前的entry都是committee的。

leader选举

leader以heartbeats的方式(AppendEntriesRPCs that carry no log entries)向follower宣示自己的存在,当follower超过一定时间未能收到leader的消息,认为leader已经故障,进入candidate状态进行leader选举。它将向所有其他节点发送RequestVote RPC,同时附上更新的term id。竞选的结果有以下2种可能

1. 竞选成功,该节点收到了多数节点的选票,每个followers有一张选票,当收到可靠的竞选请求(消息的term号没有过期),会将这张选票交出,不再响应后面相同term的竞选请求,当选的candidate会广播其竞选成功的消息,其他竞选者收到这个消息后变为follower。

2. 竞选失败,没有一个candidate成为leader,由于没有一个节点能够获得多数选票,解决方案,使用随机化的竞选超时时间,不要让多个节点在同一时刻开始竞选。

Log replication

正常的复制过程:leader将client的请求以entry的形式追加写到到所有节点上的log上,当某个entry副本数量达到多数节点,leader可以对其committee,同时继续完成剩余节点的复制。

leader与follower不一致:leader会找到第一个不一致的entry并从这个点开始同步,对于每个follower,leader会维持一个nextindexid 指向下一个发送给这个follower的entry,实现:当leader开始运作时,将所有nextindexid初始化为自己log中最后那个entry,若发出的entry冲突,leader会将这个id减一,重新发送,直到一致,并删除掉follower的log中后续不一致的entry。

Election restriction选举的限制

被选出来的leader必须包括所有committeed entry,在选举时,candidate 发出的RequestVote RPC会包括其log最新的entry的log index和term index,follower不会给那些log没有自己新的candidate投票。

不要对以前的term的entry进行committee



a:s1是leader,完成了两个节点的复制后s1故障

b:s5被选举为leader(来自s5,s4,s3的选票),收到新的请求,尚未开始复制,s5故障

c:s1恢复,重新当选为leader,继续2的复制并达到了多数节点,当尚未完成committee之前s1故障

d:s5当选为leader,继续复制并将2覆盖掉,若复制前s5对2进行committee就错了(2后来被覆盖了)

Follower and candidate crashes

Follower and candidate crashes的情况下RequestVote and AppendEntries RPCs请求会失败,raft会进行重试,对于那些完成了请求,在回复之前挂掉的server,恢复后会收到重复的请求,raft RPC是幂等的,通过检查log可以发现那些重复的请求,忽视掉。

Timing and availability

raft应在如下网络状况下运行

broadcastTime≪electionTimeout≪MTBF


Cluster membership changes



raft可以做到运行时动态增加或减少server数量而不中断服务,使用一种两阶段的方法:

设原来的配置文件为C_old,新的配置文件为C_new,为了解决突然转变配置导致的可能出现的不一致,raft加入了一个中间态,这个中间态使用新旧文件的并集作为配置文件,比如旧配置文件包括a,b,c3节点,新配置包括b,c,d节点,中间态的配置就是a,b,c,d节点。这个中间态的配置文件称为C_old,new

在修改配置的过程中,继续进行log复制的工作,并复制到所有新旧配置的节点上。

新旧配置中包括的节点中这一过程中都可以竞选为leader

agreement(包括选举和entry commitment)需要新旧配置所有server的多数同意(非常重要,不是新旧配置并集的server,而是新旧配置分别包括的server都达到多数同意)。

修改配置的方式与log复制的流程相同,新的配置文件被当作一个特殊的entry进行复制

当server接受到新的配置(包括C_new,C_old,new )会马上按照这个配置继续后续的工作,不管这个配置是否committeed

当C_old,new完成committee后,leader就可以开始进行C_new的复制工作,当C_new完成committee,旧的配置就可以不用了,那些不在新配置中的server可以关闭了。

额外需要注意的问题

新加入的节点log是空的,所以需要一定时间才能追上leader的复制进度,所以当修改配置完成以后由于这些节点的存在,新加入的entry可能没法完成committee(达到多数节点),解决方法是将这些新节点作为non-voting members(the leader replicates log entries to them, but they are not considered for majorities).,追上leader再作为正常节点。

在配置修改的过程,leader可能是不在新配置中的节点,在这种情况下,当完成新配置文件的committee后,该leader会自动退出。同时,新配置的server会选举出一个leader。

对于那些完成配置修改后被移出raft的node,由于收不到heartbeats消息会发生选举过程,干扰集群的正常工作(这里感觉没看懂,新的配置server还会接受那些被移出节点的消息?),解决方法是,当follower在heartbeats未超时之前不会接受其他节点的选举请求,也不会因为这些消息的term id更大而更新term id。

Log compaction

log会随着时间不断增长,所以需要一种方式将那些陈旧的entry从log移出。

snapshot



上图是快照的实现方式,index 5之前的entry都转为快照,相关的x,y设定为快照最后的值,快照完成后,涉及的entry就可以全部丢弃,log中只剩下2个entry,后续的client读操作可以直接读快照的结果。

何时进行快照,对多数entry进行快照由各个server自行决定。

增量压缩

每次压缩一定数量的entry,这样可以使压缩过程的开销均摊开,为了提高压缩效率,会优先选择那些包含了多次被修改的对象的区域进行压缩(They first select a region of data that has accumulated many deleted and overwritten objects, then they rewrite the live objects from that region more compactly and free the region),和快照相比这种方法显得较为复杂

问题

对于那些log复制进度远远落后于leader的follower,会出现leader下一个需要复制给那个follower的entry已经被快照化从而被丢弃的情况,为了解决这个问题,leader会向那些过于落后的follower发送

InstallSnapshot RPC,要求其复制leader的快照并抛弃那些快照中包含的entry

另外一种方法是不允许follower自己进行快照而是由leader发送快照,这样太浪费带宽。

快照实现细节:

(1)何时进行快照,过快过慢都不好,推荐的方法是当log达到一定的容量时进行

(2)如何减少快照的开销,建议使用copy_on_write

Client interaction

当client不知道哪个server是leader时,它会随机选一个发送命令,收到命令的server会回复leader地址

在某些情况下,server处理了client的命令,但是在回复client前宕机导致client重发命令,可能导致出错的。解决的方法是在client命令中附上唯一的序列号,这样server不会处理那些已经处理过的命令

为了防止读操作读出过期的无效的数据,要保证以下两点

(1)回复读操作之前leader必须知道哪些entry是committeed的,在新的leader刚开始工作时,它是不知道的,为了解决这个问题,leader应该发出完成一个空的entry的committee,raft性质决定了这个完成committee的entry之前的entry都是committeed(To find out, it needs to commit an entry from its term. Raft handles this by having each leader commit a blank no-op entry into the log at the start of its term.)

(2)leader需要确认自己并没有被移出集群,所以leader在回复client前先需要和多数节点完成一个heartbeats(Raft handles this by having the leader exchange heartbeat messages with a majority of the cluster before responding to read-only requests)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  raft