问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

Raft协议详解,分布式一致性的艺术

创作时间:
作者:
@小白创作中心

Raft协议详解,分布式一致性的艺术

引用
CSDN
1.
https://blog.csdn.net/ly853602/article/details/146306363

在分布式系统的世界里,有一个问题始终让工程师们头疼不已 — 如何让分布在不同节点上的数据保持一致?这就是著名的"分布式一致性问题"。而今天,我们要向大家介绍的Raft协议,正是解决这一问题的优秀方案之一。

与复杂难懂的Paxos协议不同,Raft协议设计的初衷就是易于理解和实现。它把复杂的一致性问题分解成了几个相对独立的子问题,让我们能够更容易地掌握它。下面,就让我们一起来探索Raft的奥秘。

Raft是什么?

Raft是一种用于管理复制日志的一致性算法。它的目标是提供与Paxos等效的功能和性能,但结构不同,使其更容易理解并且更容易构建实际系统。

简单来说,Raft就是一种让多台机器以相同顺序执行相同命令的协议,即使其中一些机器出现故障,整个系统也能继续正常工作。

Raft的核心概念

在深入了解Raft的工作原理之前,我们需要先了解几个核心概念。

角色

在Raft集群中,每个节点都可能处于以下三种角色之一:

  1. Leader(领导者) :负责处理所有客户端请求,并将日志复制到其他节点。一个Raft集群在任何时刻最多只能有一个Leader。

  2. Follower(跟随者) :被动接收来自Leader的日志复制请求。如果Follower长时间没有收到Leader的心跳,它会变成Candidate并发起选举。

  3. Candidate(候选人) :当Follower超时没有收到Leader的心跳时,会转变为Candidate并发起选举,尝试成为新的Leader。

任期(Term)

Raft将时间划分为任意长度的任期(Term)。每个任期都由一个选举开始,如果选举成功,一个Leader会在该任期内管理集群;如果选举失败,这个任期就会结束,新的任期(和新的选举)会很快开始。

任期在Raft中充当逻辑时钟的角色,每个服务器都存储当前任期号,任期号单调递增。当服务器之间通信时,会交换当前任期信息,如果一个服务器的当前任期号比其他服务器的小,它会更新自己的当前任期到较大的值。

日志复制

Leader接收客户端的命令,将这些命令作为日志条目追加到自己的日志中,然后并行地发送AppendEntries消息给其他服务器,告诉它们复制这些条目。当Leader确认日志条目已经安全地复制到大多数服务器上后,它会提交这些日志条目(即应用到状态机),并通知其他服务器。

Raft如何工作?

Raft协议主要包括三个子问题:Leader选举、日志复制和安全性保证。我们一个一个来看。

Leader选举

当Raft集群启动时,所有节点都是Follower。如果Follower在一定时间内(称为选举超时)没有收到来自Leader的心跳,它会假设没有Leader或者Leader已经失效,然后转变为Candidate开始新的选举。

选举过程如下:

  1. Follower增加当前任期号,转变为Candidate。
  2. Candidate给自己投票,并并行地向集群中的其他服务器发送RequestVote消息。
  3. 当一个Candidate收到来自集群中大多数服务器的投票时,它就成为新的Leader。
  4. 每个服务器在一个任期内最多只能投票给一个Candidate,按照先到先得的原则。
  5. 如果一个Candidate在选举超时时间内没有获胜,它会增加任期号并开始新一轮选举。

为了防止多个Candidate同时发起选举导致选票分散,Raft使用随机的选举超时时间,一般在150-300ms之间。这使得在大多数情况下,只有一个服务器会首先超时并赢得选举。

日志复制

一旦Leader被选出,它就开始为客户端请求提供服务。每个客户端请求都包含一个需要被复制状态机执行的命令。

日志复制过程如下:

  1. Leader接收客户端请求,将命令作为新的日志条目追加到自己的日志中。
  2. Leader并行地向所有Follower发送AppendEntries消息,包含新的日志条目。
  3. 当Leader确认一个日志条目已经被大多数服务器(包括自己)复制后,它认为该条目是"已提交的"。
  4. Leader将已提交的日志条目应用到自己的状态机,并返回执行结果给客户端。
  5. Leader在后续的AppendEntries消息中通知所有Follower提交这些日志条目。
  6. Follower将已提交的日志条目应用到它们自己的状态机。

如果Follower崩溃或运行缓慢,或者网络丢包,Leader会无限重试AppendEntries消息,直到所有Follower最终存储了所有日志条目。

安全性保证

Raft算法保证以下安全属性:

  1. 选举安全 :在一个给定的任期内,最多一个服务器可以当选为Leader。
  2. Leader只追加 :Leader不会覆盖或删除自己日志中的条目,只会追加新的条目。
  3. 日志匹配 :如果两个日志包含一个具有相同索引和任期的条目,则这两个日志在该索引之前的所有条目都是相同的。
  4. Leader完备性 :如果一个日志条目在某个任期被提交,那么该条目将出现在之后任期的Leader的日志中
  5. 状态机安全 :如果一个服务器已经将某个日志条目应用到它的状态机中,那么其他服务器不会在同一个日志索引位置应用一个不同的命令。

为了实现这些安全性保证,Raft增加了一个限制:只有包含了前一个任期所有已提交日志条目的Candidate才能当选为Leader。

这个图展示了Raft中可能出现的日志不一致情况。在这个例子中:

  • Leader和Follower 1的日志一致到索引9
  • Follower 2与Leader在索引4之前一致,之后的日志条目任期不匹配
  • Follower 3与Leader在索引2之前一致,之后的日志条目任期不匹配

当Leader试图将自己的日志复制给Follower时,它会强制Follower的日志变得与自己的一致。具体方法是:找到Leader和Follower共同拥有的最后一个日志条目,然后删除Follower在该点之后的所有条目,并将Leader在该点之后的条目发送给Follower。

成员变更

在实际系统中,有时需要更改集群的配置(如添加或删除服务器)。Raft使用一种称为"联合共识"的两阶段方法来确保在成员变更过程中系统的安全性。

具体步骤如下:

  1. 首先转换到一个过渡配置(称为"联合共识"),在这个配置中,新旧两种配置的服务器都参与投票和日志复制。
  2. 一旦联合共识配置被提交,系统就可以转换到新配置。
  3. 旧配置中的服务器可以安全退出,新配置中的服务器可以开始完全参与集群的工作。

这种两阶段的方法确保了在成员变更过程中,任何时候都不会有两个不同的Leader同时存在于同一个任期内。

日志压缩

随着时间的推移,Raft的日志会变得越来越长。为了防止日志无限增长,Raft使用快照机制进行日志压缩。

当服务器创建快照时,它会丢弃该快照之前的所有日志条目,只保留快照中的状态。快照包含以下信息:

  1. 状态机截至某个日志索引的完整状态。
  2. 快照中最后一个包含的日志条目的索引和任期。
  3. 集群配置信息(如果有成员变更的话)。

当Leader需要将很旧的日志条目发送给一个落后的Follower时,它可以发送快照而不是完整的日志历史,这样可以加快Follower的追赶速度。

Raft的优点和挑战

优点

  1. 可理解性 :Raft通过将一致性问题分解为独立的子问题,使其更容易理解和实现。
  2. 强一致性 :Raft保证所有服务器以相同的顺序执行相同的命令。
  3. 容错性 :只要大多数服务器正常工作,Raft就能正常运行。
  4. 成员变更安全 :Raft提供了安全的方法来更改集群成员。

挑战

  1. 性能开销 :Raft需要一定的时间来选举Leader和复制日志,可能导致系统在某些情

  2. 性能开销 :Raft需要一定的时间来选举Leader和复制日志,可能导致系统在某些情况下的响应时间增加。

  3. 多数派依赖 :Raft要求集群中的大多数节点正常工作才能提供服务。在一个有n个节点的集群中,最多只能容忍(n-1)/2个节点故障。

  4. 网络分区处理 :当网络分区发生时,少数派分区内的节点将无法进行写操作,这可能导致系统的部分可用性下降。

  5. 读取一致性 :在某些实现中,为了确保读取的一致性,可能需要与Leader通信,这会增加读取操作的延迟。

Raft与其他一致性算法的比较

在分布式一致性算法领域,Raft主要与Paxos和ZAB(ZooKeeper Atomic Broadcast)算法进行比较。

Raft vs Paxos

  • 可理解性 :Raft的设计初衷就是为了比Paxos更容易理解和实现。Paxos的论文晦涩难懂,而Raft将问题分解为Leader选举、日志复制和安全性三个子问题。
  • 角色划分 :Paxos中的角色(Proposer、Acceptor、Learner)更加抽象,而Raft的角色(Leader、Follower、Candidate)更直观。
  • 状态机复制 :Paxos本身只是一个单一决策的共识算法,需要额外的机制来实现完整的状态机复制,而Raft内置了这种支持。

Raft vs ZAB

  • 设计目标 :ZAB专门为ZooKeeper设计,而Raft是一个通用的一致性算法。
  • 消息处理 :ZAB使用ZXID(由epoch和计数器组成)来标识事务,而Raft使用任期号和日志索引的组合。
  • Leader选举 :ZAB选举过程基于ZXID的大小,而Raft使用随机超时机制。
  • 成员变更 :Raft有内置的联合共识机制处理成员变更,而ZAB需要额外的协议。

Raft协议的实际应用

Raft协议已经在许多开源和商业系统中被广泛采用。以下是一些使用Raft的知名项目:

  1. etcd :CoreOS开发的分布式键值存储系统,被Kubernetes用作配置存储。
  2. Consul :HashiCorp开发的服务发现和配置工具。
  3. TiKV :一个分布式事务键值数据库,是TiDB的存储层。
  4. CockroachDB :可伸缩的SQL数据库。
  5. InfluxDB :时序数据库的集群版本。

Raft的实现细节和优化

虽然Raft的基本算法相对简单,但实际实现中还有许多细节需要考虑:

预投票机制

在标准Raft中,当Follower超时后,它会增加任期号并开始新的选举。这可能导致网络不稳定时出现过多的选举。预投票机制要求Candidate在真正开始选举前先进行一轮"试探",只有在确认能获得多数票时才正式开始选举。

日志条目批处理

在高吞吐量场景下,将多个客户端请求批量添加到一个日志条目中可以提高性能。

读取优化

标准Raft要求所有读取也经过Leader,以确保读取的数据是最新的。但这会增加读取延迟。一些优化包括:

  1. ReadIndex :Leader确认自己仍是Leader后,记录当前已提交的日志索引,等到状态机应用到该索引后再响应读请求。
  2. Lease Read :Leader使用时间限制的租约,在租约期内可以直接响应读请求而无需额外确认。

非投票成员

一些Raft实现支持非投票成员,这些成员接收日志但不参与投票。这对于构建大型只读副本集群很有用。

结语

Raft协议作为一种设计用于易于理解和实现的分布式一致性算法,已经成功地在许多系统中得到了应用。它通过将复杂的问题分解为Leader选举、日志复制和安全性三个相对独立的子问题,使得工程师能够更容易地理解和实现它。

虽然Raft不是性能最优的一致性算法,但它的可理解性和实现简洁性使其成为许多分布式系统的首选。通过各种优化,Raft也能在实际应用中达到很好的性能。

随着分布式系统在现代技术架构中的重要性不断提升,理解Raft这样的基础一致性协议变得越来越重要。希望这篇文章能帮助你了解Raft的核心概念和工作原理,为你在分布式系统设计和实现中提供有价值的参考。

如果你对Raft感兴趣,建议阅读原论文《In Search of an Understandable Consensus Algorithm》,以及各种开源实现的源代码,这将有助于更深入地理解Raft的细节和优化。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号