分布式一致性之raft算法

Posted 看,未来

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分布式一致性之raft算法相关的知识,希望对你有一定的参考价值。

一句话简介ratf算法

没听过不要紧,我原先也没听过。

Raft 算法是通过一切以领导者为准的方式实现一系列值的共识和各节点日志的一致
熟悉吗?redis的哨兵用的就是这一套,不过哨兵简化了一些部分,提升了运行效率,降低了一致性,保证了最终一致性。

晕吗?晕就完蛋了。


分布式一致性的难点

1、时钟不一致
如果两条命令,分别为 A、B,被发往两个节点。由于网络延迟等原因,导致一个节点先收到A,再收到B;另一个节点先收到B,再收到A,这时候就有可能会造成数据的不一致性。
在一个节点上,可以通过时间区分操作的先后顺序,但是在多个节点上,由于物理时钟难以同步,所以我们无法直接再分布式系统中直接使用物理时钟区分事件时序。

2、网络不可靠
可能一个节点根本就没有收到命令B呢?

3、节点崩溃


CAP理论

分区容错性:正常情况下,一个集群内所有的节点网络应该是互通的,但由于网络不可靠,可能导致一些节点之间网络不通,整个网络被分为几块区域。出现网络不通后,其他不连通的分区就访问不到这个节点的数据了(如果是独苗就坏事儿了)。通常将数据复制到集群的所有节点,保证及时出现网络分区后,不同网络分区都可以访问到数据。

一致性:集群中所有节点的数据保持一致。

可用性:集群一致处于可用状态。

传说这三者几乎不可兼得。如果要分区容错性,很难保证一致性,具体原因往上看。如果要一致性,又要分区一致性,那就是数据不一致就直接关掉服务咯。所以三者几乎不可兼得。

所以现在用的比较多的是:最终一致性。
就是在满足分区容错的情况下,允许在同步的过程中数据偶尔出现不一致,只要同步完之后每个节点的数据保持一致就可以。

了解更多关于分布式事务的可以看一下这篇:聊聊分布式事务


分布式一致性:Raft算法

共识算法就是保证一个集群的多台机器协同工作,在遇到请求时,数据能够保持一致。即使遇到机器宕机,整个系统仍然能够对外保持服务的可用性。

Raft将共识问题分解三个子问题:

Leader election 领导选举:有且仅有一个leader节点,如果leader宕机,通过选举机制选出新的leader;

Log replication 日志复制:leader从客户端接收数据更新/删除请求,然后日志复制到follower节点,从而保证集群数据的一致性;

Safety 安全性:通过安全性原则来处理一些特殊case,保证Raft算法的完备性;

所以,Raft算法核心流程可以归纳为:

首先选出leader,leader节点负责接收外部的数据更新/删除请求;

然后日志复制到其他follower节点,同时通过安全性的准则来保证整个日志复制的一致性;

如果遇到leader故障,followers会重新发起选举出新的leader;

这里先介绍一下日志同步的概念:服务器接收客户的数据更新/删除请求,这些请求会落地为命令日志。只要输入状态机的日志命令相同,状态机的执行结果就相同。所以Raft的核心就是leader发出日志同步请求,follower接收并同步日志,最终保证整个集群的日志一致性。


选举过程

当我们启动一个新的Raft集群或某个领导者不可用时,将通过集群中所有成员节点之间协商来选举一个新的领导者。

Raft使用基于心跳的RPC机制来检测何时开始新的选举。 在正常期间,Leader会定期向所有可用的Follower发送心跳消息(实际中可能把日志和心跳一起发过去)。 因此,其他节点以Follower状态启动,只要它从当前Leader那里收到周期性的心跳,就一直保持在Follower状态。

如果追随者在一段时间内未收到心跳消息,就会触发选举超时,该选举超时将启动新的选举以选择领导者。

当Follower达到其超时时间时,它将通过以下方式启动选举程序:

增加当前Term,为自己投票
并将“ RequestVote” RPC发送给集群中的所有其他人,这时也就是从Follower转换为Candidate

根据Candidate从集群中其他节点收到的响应,可以得出选举的三个结果。

1、如果大多数节点以“是”投票支持RequestVote请求,则候选人S1赢得选举。
2、在S1等待期间,它可能会从另一个声称是领导者的节点接收AppendEntries RPC。 如果S1的候选Term低于AppendEntries RPC的接收Term,则候选S1放弃并接受另一个节点作为合法领导者。
3、拆分投票方案:当有多个Follower同时成为Candidate时,任何候选人都无法获得多数。 这被称为分裂投票情况。 在这种情况下,每个Candidate都将超时,并且将触发新的选举。

为了最大程度地减少拆分投票的情况,Raft使用了随机选举超时机制,该机制将随机超时值分配给每个节点。

新官上任

一旦节点成为Leader,它就可以从客户端接收命令/日志条目。 使用AppendEntries RPC发送日志条目。

从客户端收到命令后,Leader将为命令分配Term和日志索引Index。 然后,Leader尝试在集群中的大多数节点上执行复制命令。 如果复制成功,则将命令提交给集群,并将响应发送回客户端。

Leader将命令附加到日志,并使用该命令广播AppendEntries RPC。

每个节点都在本地申请条目并成功答复。当大多数跟随者节点已在本地成功提交日志条目时,Leader将提交(前一阶段相当于Try,接下来是Commit,类似两阶段提交协议)命令并将成功响应发送回客户端。当领导者提交日志条目时,它还会更新提交索引,并且下一条AppendEntries广播消息会将更新的提交索引复制到所有跟随者节点。当领导者提交一个条目时,它还将在当前日志索引之前提交所有全部内容。

如果某些节点不可用于接收日志条目,或者消息在运行中丢失,则日志中可能存在不一致之处。Leader负责调和此类不一致。 当Follower收到AppendEntries RPC时,它也包含Term和上一个日志条目的日志索引。 它与Follower日志的最后一个条目不匹配,那么Follower将发送失败的响应。 因此,Leader知道该特定节点的日志中存在不一致之处。

领导者通过跟踪每个Follower的nextIndex来解决日志不一致问题。 当给定的Follower的日志不一致时(即,如果发送的响应失败),则Leader递减nextIndex值,然后重试AppendEntries RPC。 此过程将继续进行,直到Follower日志与领导者一致为止。 此外,每个节点还将本地日志保存在持久存储中。


根正苗红

当前的Leader election 领导选举和Log replication 日志复制并不能保证Raft算法的安全性,在一些特殊情况下,可能导致数据不一致,所以需要引入下面安全性规则。

(1)Election Safety 选举安全性:避免脑裂问题

选举安全性要求一个任期Term内只能有一个leader,即不能出现脑裂现象,否者raft的日志复制原则很可能出现数据覆盖丢失的问题。Raft算法通过规定若干投票原则来解决这个问题:

一个任期内,follower只会投票一次票,且先来先得;

Candidate存储的日志至少要和follower一样新;

只有获得超过半数投票才有机会成为leader;

(2)Leader Append-Only 日志只能由leader添加修改

Raft算法规定,所有的数据请求都要交给leader节点处理,要求:

leader只能日志追加日志,不能覆盖日志;

只有leader的日志项才能被提交,follower不能接收写请求和提交日志;

只有已经提交的日志项,才能被应用到状态机中;

选举时限制新leader日志包含所有已提交日志项;

(3)Log Matching 日志匹配特性

这点主要是为了保证日志的唯一性,要求:

如果在不同日志中的两个条目有着相同索引和任期号,则所存储的命令是相同的;

如果在不同日志中的两个条目有着相同索引和任期号,则它们之间所有条目完全一样;

(4)Leader Completeness 选举完备性:leader必须具备最新提交日志

Raft规定:只有拥有最新提交日志的follower节点才有资格成为leader节点。具体做法:candidate竞选投票时会携带最新提交日志,follower会用自己的日志和candidate做比较。

如果follower的更新,那么拒绝这次投票;

否则根据前面的投票规则处理。这样就可以保证只有最新提交节点成为leader;

因为日志提交需要超过半数的节点同意,所以针对日志同步落后的follower(还未同步完全部日志,导致落后于其他节点)在竞选leader的时候,肯定拿不到超过半数的票,也只有那些完成同步的才有可能获取超过半数的票成为leader。

日志更新判断方式是比较日志项的term和index:

如果TermId不同,选择TermId最大的;

如果TermId相同,选择Index最大的;

(5)State Machine Safety 状态机安全性:确保当前任期日志提交

Raft对日志提交有额外安全机制:leader只能提交当前任期Term的日志,旧任期Term(以前的数据)只能通过当前任期Term的数据提交来间接完成提交。简单的说,日志提交有两个条件需要满足:

当前任期;

复制结点超过半数;

仍需努力

1、Raft严格是单个Leader协议,而且太多的流量会阻塞系统,存在解决此瓶颈的Paxos算法的某些变体。
2、有许多假设在起作用,降低了现实生活中的适用性。
3、K + 1的复制服务器可以容忍K服务器中的关闭/故障。

以上是关于分布式一致性之raft算法的主要内容,如果未能解决你的问题,请参考以下文章

分布式一致性之raft算法

分布式系统之Raft共识算法

Raft协议之领导者选举

一致性协议Raft算法

分布式一致性算法——Paxos 和 Raft 算法

深入浅出etcd之raft实现