文章目录
简单介绍
Etcd 是一个高可用、强一致的分布式键值(Key-Value)数据库,主要用途是共享配置和服务发现。
那Etcd是如何保证强一致性的呢?昨天面试就被问到这个问题,当时没有答上来,就很尴尬。
其实,其内部采用 Raft 算法作为分布式一致性协议,因此,Etcd 集群作为一个分布式系统“天然” 具有强一致性;而副本机制(一个 Leader,多个 Follower)又保证了其高可用性(点击进入 链接: Etcd 官网)。
所以这里我们重点介绍一下Etcd底层运用的分布式一致性算法Raft。
Raft介绍
————在正式开始介绍 Raft 协议之间,我们有必要简单介绍 下其相关概念 在分布式系统中,
一致性是比较常见的概念,所谓一致性指的是集群中的多个节点在状态上达成一 致。在程序和
操作系统不会崩惯、硬件不会损坏、服务器不会掉电、网络绝对可靠且没有延迟的理想情况下,
我们可以将集群中的 个节点看作一个整体,此时要保证它们的 致性并不困难。
————但是在现实的场景中,很难保证上述极端的条件全部满足,节点之间的一 致性也就很难保
证,这样就需 Paxo ,Raft 等一致性协议。一致性协议可以保证在集群中大部分节点可用的
情况下 ,集群依然可以工作并给出一个正确的结果,从而保证依赖于该集群的其他服务不受影
响。这里的“大部分节点可用”指的是集群中超过半数以上的节点可用,例如,集群中共有5
个节点,此时其中有 2个节点出现故障岩机 剩余的可用节点数为3 ,此时,集群中大多数节
点处于可用的状态,从外部来看集群依然是可用的.
————常见的一致性算法有 Paxos ,Raft 等, Paxos 协议是 Les li Lamport 1990 年提出的一种基
于消息传递的、具有高度容错特性的 致性算法, Paxos 算法解决的主要问题是分布式系统内
如何就某个值达成 在相当长的一段时间内, Paxos 算法几乎成为一 致性算法的代名词,
但是 Paxos 有两个明显的缺点:第 1个也是最明显的缺点就是 Paxos 算法难以理解, Paxos
法的论文本身就比较晦涩难懂,要完全理解 Paxos 协议需要付出较大的努力,很多经验丰富的
开发者在看完 Paxos 论文之后,无法将其有效地应用到具体工程实践中,这明显增加了工程化
的门槛,也正因如此,才出现了几次用更简单的术语来解释 Paxos 的尝试, Paxos 算法的第2
个缺点就是它没有提供构建现实系统的良好基础 ,也有很多工程化 Paxos 算法的尝试,但是它
Paxos 算法本身做了 较大的改动,彼此之间的实现差距都 较大,实现的功能和目的都
有所不同,同时与 Paxos 算法的描述有很多出入。
————正因为上述的缺点,导致 Paxos 协议处于一种比较尴尬的境地:在理论上 Paxos 算法是正
确可行的,但是实际的工程中很少有与 Paxos 算法类似的实践,也正因为如此,人们开始寻找新的一致性算法,寻找的结果也就是本文介绍的重点一-Raft 协议。
————Raft 算法是一种用于管理复制日志的 致性算沽,其功能与 Paxos 算法相同类似,但其算法结
构和 Paxos 算法不同,在设计 Raft算法时设计者就将易于理解作为其目标之一 ,这使得 Ratf法更
易于构建实际的系统,大幅度减少了工程化的工作 ,也方便开发者此基础上进行扩展。虽然 Raft
论文己经很好理解,但是本章并不打算直接翻译 Raft论文,而是尽可能通过示例介绍企协议如
何处理各种不同的场景,并且介绍 Raft 协议中的 Lea er 选举和日志复制等方面的内容。
Raft角色
————根据官方文档,一个Raft集群包含若干节点,总共分为三种角色:Leader、Follower和Candidate,每种角色的任务也不一样,正常情况下,一个集群只有Leader和Follower两种角色存在。
Leader(领导者):负责日志的同步管理,处理来自客户端的请求,与Follower保持heartBeat的联系;
Follower(追随者):响应 Leader 的日志同步请求,响应Candidate的邀票请求,以及把客户端请求到Follower的事务转发(重定向)给Leader;
Candidate(候选者):负责选举投票,集群刚启动或者Leader宕机时,状态为Follower的节点将转为Candidate并发起选举,选举胜出(获得超过半数节点的投票)后,从Candidate转为Leader状态。
一致性需求的子问题拆分
为了实现一致性,Raft将一致性问题分解拆分成三个相对独立的子问题:
选举(Leader Election):当 Leader 宕机或者集群初创时,一个新的 Leader 需要被选举出来;
日志复制(Log Replication):Leader 接收来自客户端的请求并将其以日志条目的形式复制到集群中的其它节点,并且强制要求其它节点的日志和自己保持一致;
安全性(Safety):如果有任何的服务器节点已经应用了一个确定的日志条目到它的状态机中,那么其它服务器节点不能在同一个日志索引位置应用一个不同的指令。
选举(Leader Election)
————Raft 协议的工作模式是 Leade 节点和 多个 Fo ll ow 节点的模式,也就是常说的
Leader-Follow 模式。在 Raft 协议中,每个节点都维护了一 个状态机,该状态机有 三种状态,
分别是 Leade 状态、 Follower 状态和 Candidate 状态,在任意时刻,集群中的任意一个节点都
处于这 个状态之一。
在多数情况下,集群中有 一个Leader 节点,其他节点都处于 Follower 状态
阶段1:所有节点都是Follower
上面提到,一个应用 Raft 协议的集群在刚启动(或 Leader 宕机)时,所有节点的状态都是 Follower,初始 Term(任期)为 0。同时启动选举定时器,每个节点的选举定时器超时时间都在 100~500 毫秒之间且并不一致(避免同时发起选举)。
阶段2:Follower转换为Candidate并发起投票
没有 Leader,Followers 无法与 Leader 保持心跳(Heart Beat),节点启动后在一个选举定时器周期内未收到心跳和投票请求,则状态转为候选者 Candidate 状态,且 Term 自增,并向集群中所有节点发送投票请求并且重置选举定时器。
注意,由于每个节点的选举定时器超时时间都在 100-500 毫秒之间,且彼此不一样,以避免所有 Follower 同时转为 Candidate 并同时发起投票请求。换言之,最先转为 Candidate 并发起投票请求的节点将具有成为 Leader 的“先发优势”。
阶段3:投票策略
节点收到投票请求后会根据以下情况决定是否接受投票请求:
请求节点的 Term 大于自己的 Term,且自己尚未投票给其它节点,则接受请求,把票投给它;
请求节点的 Term 小于自己的 Term,且自己尚未投票,则拒绝请求,将票投给自己。
阶段4:Candidate转为Leader
一轮选举过后,正常情况下,会有一个 Candidate 收到超过半数节点(N/2 + 1)的投票,它将胜出并升级为 Leader。然后定时发送心跳给其它的节点,其它节点会转为 Follower 并与 Leader 保持同步,到此,本轮选举结束。
注意:有可能一轮选举中,没有 Candidate 收到超过半数节点投票,那么将进行下一轮选举。
日志复制(Log Replication)
————在一个 Raft 集群中,只有 Leader 节点能够处理客户端的请求(如果客户端的请求发到了 Follower,Follower 将会把请求重定向到 Leader),客户端的每一个请求都包含一条被复制状态机执行的指令。Leader 把这条指令作为一条新的日志条目(Entry)附加到日志中去,然后并行得将附加条目发送给 Followers,让它们复制这条日志条目。
————当这条日志条目被 Followers 安全复制,Leader 会将这条日志条目应用到它的状态机中,然后把执行的结果返回给客户端。如果 Follower 崩溃或者运行缓慢,再或者网络丢包,Leader 会不断得重复尝试附加日志条目(尽管已经回复了客户端)直到所有的 Follower 都最终存储了所有的日志条目,确保强一致性。
————Leader选出后,就开始接收客户端的请求。Leader把请求作为日志条目(Log entries)加入到它的日志中,然后并行的向其他服务器发起 AppendEntries RPC复制日志条目。当这条日志被复制到大多数服务器上,Leader将这条日志应用到它的状态机并向客户端返回执行结果。
————某些Followers可能没有成功的复制日志,Leader会无限的重试 AppendEntries RPC直到所有的Followers最终存储了所有的日志条目。
日志由有序编号(log index)的日志条目组成。每个日志条目包含它被创建时的任期号(term),和用于状态机执行的命令。如果一个日志条目被复制到大多数服务器上,就被认为可以提交(commit)了。