CAP&RAFT

一、CAP 理论和 BASE 理论

理论是指导业界实现的纲领,也是提炼了多年研究的精华,在分布式一致性领域,最主要的指导理论是 CAP 和 BASE 两个。

1. CAP 理论

CAP 理论是 Eric Brewer 教授在 2000 年提出 的,是描述分布式一致性的三个维度,分别是指:

(1)一致性(Consistency)

每次读操作都能保证返回的是最新数据;在分布式系统中,如果能针对一个数据项的更新执行成功后,所有的请求都可以读到其最新的值,这样的系统就被认为具有严格的一致性。

(2)可用性(Availablity)

任何一个没有发生故障的节点,会在合理的时间内返回一个正常的结果,也就是对于每一个请求总能够在有限时间内返回结果。

(3)分区容忍性(Partition-torlerance)

当节点间出现网络分区,照样可以提供满足一致性和可用性的服务,除非整个网络环境都发生了故障。那么,什么是网络分区呢?分区是系统中可能发生的故障之一,可能有节点暂时无法提供服务:发生了像 长时间 GC、CPU 死循环、链接池耗尽或者是网络通信故障等问题。

 

CAP 指出,一个分布式系统只能满足三项中的两项而不可能满足全部三项。举例来看:如下图所示,假设有五个节点:n1~n5 ,因网络分区故障被分成两组:

[n1、n2]和[n3~n5],那么当 n1 处理客户端请求时(为了支持"容忍网络分区",即支持 P):

  1. 如果要保证 C(一致性),那么它需要把消息复制到所有节点,但是网络分区导致无法成功复制到 n3~n5,所以它只能返回"处理失败"的结果给客户端。(这时系统就处于不可用状态,即丧失了 A) 

  2. 如果要保证可用性 A,那么 n1 就只能把消息复制到 n2,而不用复制到 n3~n5(或者无视复制失败/超时),但 n3 同时也可能在处理客户端请求,n3 也为了保证 A 而做了同样的处理。那么 [n1、n2]和[n3~n5]的状态就不一致了,于是就丧失了 C(一致性)。

  3. 如果不容忍网络分区,则 P(分区容忍性)不能满足。

既然 CAP 理论无法全部满足,为了指导工业实现,就需要降低标准,因此出现了 BASE 理论。

2. BASE 理论

BASE 理论是 eBay 的架构师 Dan Pritchett 提出的,它的思想是:“即使无法做到强一致性,但每个应用都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性” 。

BASE 理论有三项指标:

  • 基本可用(Basically Available):是指分布式系统在出现不可预知故障的时候,允许损失部分可用性:比如响应时间、功能降级等;

  • 软状态( Soft State):也称为弱状态,是指允许系统中的数据存在中间状态,并认为该中间状态的存在不会影响系统的整体可用性,即允许系统在不同节点之间进行数据同步的过程存在延时;

  • 最终一致性( Eventual Consistency):强调的是系统中所有的数据副本,在经过一段时间的同步后,最终能够达成一致的状态。

BASE 理论面向的是大型高可用、可扩展的分布式系统。BASE 通过牺牲强一致性来获得可用性,并允许数据短时间内的不一致,但是最终达到一致状态。

 

2. Raft 算法

Paxos 协议从被提出,一直是分布式一致性算法的标准协议,但是它不易理解,对于工程师来说实现起来很复杂,以至于算法提出近 30 年都没有一个完全版的实现方案。业界很多实现都是 Paxos-like。

Raft 算法是斯坦福大学 2017 年提出,论文名称《In Search of an Understandable Consensus Algorithm》,望文生义,该算法的目的是易于理解。Raft 这一名字来源于"Reliable, Replicated, Redundant, And Fault-Tolerant"(“可靠、可复制、可冗余、可容错”)的首字母缩写。

Raft 使用了分治思想把算法流程分为三个子问题:选举(Leader election)、日志复制(Log replication)、安全性(Safety)三个子问题。

  • Leader 选举:当前 leader 跪了或集群初始化的情况下,新 leader 被选举出来。

  • 日志复制:leader 必须能够从客户端接收请求,然后将它们复制给其他机器,强制它们与自己的数据一致。

  • 安全性:如何保证上述选举和日志复制的安全,使系统满足最终一致性。

(1)概念介绍

在 Raft 中,节点被分为 Leader Follower Cabdidate 三种角色:

  • Leader:处理与客户端的交互和与 follower 的日志复制等,一般只有一个 Leader;

  • Follower:被动学习 Leader 的日志同步,同时也会在 leader 超时后转变为 Candidate 参与竞选;

  • Candidate:在竞选期间参与竞选;

 

Term:是有连续单调递增的编号,每个 term 开始于选举阶段,一般由选举阶段和领导阶段组成。

 

随机超时时间:Follower 节点每次收到 Leader 的心跳请求后,会设置一个随机的,区间位于[150ms, 300ms)的超时时间。如果超过超时时间,还没有收到 Leader 的下一条请求,则认为 Leader 过期/故障了。

心跳续命:Leader 在当选期间,会以一定时间间隔向其他节点发送心跳请求,以维护自己的 Leader 地位。

(2)协议流程

a. 选举流程

当某个 follower 节点在超时时间内未收到 Leader 的请求,它则认为当前 Leader 宕机或者当前无 Leader,将发起选举, 既从一个 Follower 变成 Candidate。

这个转变过程中会发生四件事:

  • 增加本地节点的 Current Term 值;

  • 将状态切换为 Candidate;

  • 该节点投自己一票;

  • 批量向其他节点发送拉票请求(RequestVote RPC)。

在这个过程中,其他 Follower 节点收到拉票请求后,需要判断请求的合法性,然后为第一个到达的合法拉票请求进行投票。投票过程对于 Follower 的约束有三点:

  • 在一个任期 Term 中只能投一张票;

  • 候选人的 Term 值大于 Current Term,且候选人已执行的 Log 序号不低于本地 Log(Log 及已执行的概念见《日志复制》小节),则拉票请求是合法的;

  • 只选择首先到达的合法拉票请求;

如果一个 Candidate 收到了超过半数的投票,则该节点晋升为 Leader,会立刻给所有节点发消息,广而告之,避免其余节点触发新的选举;开始进行日志同步、处理客户端请求等。

如果一次选举中,Candidate 在选举超时时间内没有收到超过半数的投票,也没有收到其他 Leader 的请求,则认为当前 Term 选举失败,进入下一个选举周期。

 

b. 日志复制

在了解日志同步前,需要了解“复制状态机”这个概念。

复制状态机(Replicated state machines)是指:不同节点从相同的初始状态出发,执行相同顺序的输入指令集后,会得到相同的结束状态。

If two identical, deterministic processes begin in the same state and get the same inputs in the same order, they will produce the same output and end in the same state.

分布式一致性算法的实现是基于复制状态机的。

在 Raft 算法中,节点初始化后具有相同初始状态。为了提供相同的输入指令集这个条件,raft 将一个客户端请求(command)封装到一个 log entry 中。Leader 负责将这些 log entries 复制到所有的 Follower 节点,然后节点按照相同的顺序应用 commands,达到最终的一致状态。

当 Leader 收到客户端的写请求,到将执行结果返回给客户端的这个过程,从 Leader 视角来看经历了以下步骤:

  • 本地追加日志信息;

  • 并行发出 AppendEntries RPC 请求;

  • 等待大多数 Follower 的回应。收到查过半数节点的成功提交回应,代表该日志被复制到了大多数节点中(committed);

  • 在状态机上执行 entry command。既将该日志应用到状态机,真正影响到节点状态(applied);

  • 回应 Client 执行结果;

  • 确认 Follower 也执行了这条 command;如果 Follower 崩溃、运行缓慢或者网络丢包,Leader 将无限期地重试 AppendEntries RPC,直到所有 Followers 应用了所有日志条目。

 

logs 由顺序排列的 log entry 组成 ,每个 log entry 包含 command 和产生该 log entry 时的 leader term。从上图可以看到,五个节点的日志并不完全一致,raft 算法为了保证高可用,并不是强一致性,而是最终一致性,leader 会不断尝试给 follower 发 log entries,直到所有节点的 log entries 都相同。

在前面的流程中,leader 只需要日志被复制到大多数节点即可向客户端返回,而一旦向客户端返回成功消息,那么系统就必须保证 log 在任何异常的情况下都不会发生回滚。

这里推荐两个 Raft 算法动画演示,通过动画能够对 Raft 算法的选举和日志复制过程有直观清晰的认知。

  • raft step by step 入门演示: http://thesecretlivesofdata.com/raft/

  • raft 官方演示: https://raft.github.io/

在动画演示中,可以通过调整时间流速和时间轴来观察节点间通信。

 

也可以通过单击节点或者请求包来查看节点的具体状态和请求包的数据。

 

3. 安全性及约束

(1)选举安全性

即任一任期内最多一个 leader 被选出。在一个集群中任何时刻只能有一个 leader。系统中同时有多余一个 leader,被称之为脑裂(brain split),这是非常严重的问题,会导致数据的覆盖丢失。

在 raft 中,通过两点保证了这个属性:

  • 一个节点某一任期内最多只能投一票;而节点 B 的 term 必须比 A 的新,A 才能给 B 投票。

  • 只有获得多数投票的节点才会成为 leader。

(2)日志 append only

首先,leader 在某一 term 的任一位置只会创建一个 log entry,且 log entry 是 append-only。

其次,一致性检查。leader 在 AppendEntries 请求中会包含最新 log entry 的前一个 log 的 term 和 index,如果 follower 在对应的 term index 找不到日志,那么就会告知 leader 日志不一致, 然后开始同步自己的日志。同步时,找到日志分叉点,然后将 leader 后续的日志复制到本地。

(3)日志匹配特性

如果两个节点上的某个 log entry 的 log index 相同且 term 相同,那么在该 index 之前的所有 log entry 应该都是相同的。

Raft 的日志机制提供两个保证,统称为 Log Matching Property:

  • 不同机器的日志中如果有两个 entry 有相同的偏移和 term 号,那么它们存储相同的指令。

  • 如果不同机器上的日志中有两个相同偏移和 term 号的日志,那么日志中这个 entry 之前的所有 entry 保持一致。

(4)Leader 完备性 

被选举人必须比自己知道的更多(比较 term 、log index)。

如果一个 log entry 在某个任期被提交(committed),那么这条日志一定会出现在所有更高 term 的 leader 的日志里面 。选举人必须比自己知道的更多(比较 term,log index)如果日志中含有不同的任期,则选最新的任期的节点;如果最新任期一致,则选最长的日志的那个节点。

选举安全性中包含了 Leader 完备性

(5)状态机安全性

状态机安全性由日志的一致来保证。在算法中,一个日志被复制到多数节点才算 committed, 如果一个 log entry 在某个任期被提交(committed),那么这条日志一定会出现在所有更高 term 的 leader 的日志里面。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值