Raft协议和ZAB协议
Raft协议和ZAB协议
分布式系统设计中,在极大提高可用性、容错性的同时,带来了一致性问题(CAP理论)。Raft协议和ZAB协议是在分布式系统中为保证一致性而设计的协议,旨在处理CAP理论中的一致性问题,同时在面对分区容忍性和可用性方面进行权衡。
一、Raft协议
1. Raft协议是什么?
Raft协议是一种分布式一致性算法(共识算法),它是为了替代复杂难懂的 Paxos 算法而生的。共识就是多个节点对某一个事件达成一致的算法,即使出现部分节点故障,网络延时等情况,也不影响各节点,进而提高系统的整体可用性。
Raft算法将分布式一致性分解为多个子问题,包括 Leader选举(Leader election)、日志复制(Log replication)、安全性(Safety)、日志压缩(Log compaction)等。
2. 系统中的角色
Raft 协议将系统中的角色分为领导者(Leader)、跟从者(Follower)和候选者(Candidate)。
1)领导者(Leader)
Leader是Raft协议中协调集群一致性、处理客户端请求和管理日志复制的核心节点。Leader 负责处理客户端请求并将操作日志复制到 Followers(跟随者)上,只有 Leader 才能处理写操作。
2)跟从者(Follower)
接受并持久化Leader同步的日志,在Leader告知日志可以提交后,提交日志。当Leader出现故障时,主动推荐自己为候选人(Candidate)。
3)候选者(Candidate)
Leader选举过程中的临时角色。向其他节点发送请求投票信息,如果获得大多数选票,则晋升为Leader。
3. 任期选举
Raft 要求系统在任意时刻最多只有一个Leader,正常工作期间只有Leader和Follower,Raft算法将时间划分为任意不同长度的任期(Term),每一任期的开始都是一次选举,一个或多个候选人会试图成为Leader,在成功选举Leader后,Leader会在整个任期内管理整个集群:负责处理所有的客户端交互,日志复制等,Follower 仅仅响应领导者的请求。如果Leader选举失败,该任期就会因为没有Leader而结束,开始下一任期,并立刻开始下一次选举。
如下图:
4. Leader选举
Raft协议的Leader选举流程是其核心部分之一,目的是确保集群中始终只有一个领导者(Leader),并且在发生故障时能快速选举出新的领导者。这个过程能够保证日志的顺序性和一致性。
选举流程大致如下:
Raft使用心跳机制来触发领导者选举,当服务器启动时,初始化都是Follower身份,由于没有Leader,Followers无法与Leader保持心跳,因此,Followers会认为Leader已经下线,进而转为Candidate状态,然后Candidate向集群其他节点请求投票,同意自己成为Leader,如果Candidate收到超过半数节点的投票(N/2 +1),它将获胜成为Leader。
如下图:
Leader 向所有Follower周期性发送心跳包,如果Follower在选举超时时间内没有收到Leader的心跳包,就会等待一段随机的时间后发起一次Leader选举。
如下图:
1)唯一投票
在Raft协议中,一个节点在一次任期(term)内只能投一次票。这是为了防止同一候选者在一轮选举中获得多次投票,或者多个候选者在同一轮选举中都获得同一节点的投票,从而确保选举的公正性。
在进入选举投票时,每个节点都会先给自己投票,那会不会出现所有的节点都给自己投票呢?注意上述中 Candidate 和 Follower 的区别。
Follower 在选举超时期间没有接收到 Leader 的心跳,它就会把自己标记为 Candidate,成为 Candidate 后才会给自己投票,并给其他节点发起请求投票。但每个节点的超时时间都是随机的(通常在150ms到300ms之间),所以所有 Follower 节点进入 Candidate 状态的时间是不一样的。当第一个 Candidate 发送请求投票给其他节点时,其他节点基本还是 Follower 状态,还没有把票投给自己。
同样如果第一轮选举失败,要发起下一轮选举。每个节点还是经过随机的不同超时时间后,再进入 Candidate 状态。
2)任期
在Raft协议中,任期被用作逻辑时钟,并用于解决冲突。每当选举开始时,候选者都会增加它们的任期。这样可以确保每一轮选举都有一个唯一的标识,同时也能防止过期的选举结果影响新的选举。
如果第一轮选举失败了,第二轮选举开始时,候选者依然会首先增加它们的任期。例如,假设一个节点在第一轮选举中没有获得足够的投票,然后开始第二轮选举。此时,如果它没有增加其任期,那么就可能出现一个问题:这个节点可能同时在第一轮和第二轮选举中都是候选者。这将导致混乱,因为其他节点可能不知道他们应该对哪一轮选举进行投票。
5. 日志同步
Raft算法实现日志同步的具体过程如下:
1)Leader收到来自客户端的请求,将之封装成log entry并追加到自己的日志中;
2)Leader并行地向系统中所有节点发送日志复制消息;
3)接收到消息的节点确认消息没有问题,则将log entry追加到自己的日志中,并向Leader返回ACK表示接收成功;
4)Leader若在随机超时时间内收到超过半数节点的ACK,则将该log entry应用到状态机并向客户端返回成功。
如下图:
6. 总结
Raft协议会先选举出Leader,Leader完全负责日志复制的管理和负责接受所有客户端更新请求,然后复制到Follower,并在“安全”的时候执行这些请求,如果Leader故障,Follower会重新选举出新的Leader,保证一致性。
二、ZAB协议
1. ZAB协议是什么?
ZAB 协议主要是用在 ZooKeeper 集群中。同 Raft协议一样,都是为了替代复杂难懂的 Paxos 算法,二者的相似度很高。
ZAB 协议是专为 Zookeeper 的分布式协调和强一致性要求而设计的。尽管与 Raft、Paxos 等协议在实现上有相似之处,但 ZAB 更专注于处理事务日志的广播、Leader 选举和快速故障恢复。
2. ZAB 协议核心
在 Zookeeper 中只有一个 Leader,并且只有 Leader 可以处理外部客户端的事务请求,并将其转换成一个事务 Proposal(写操作),然后 Leader 服务器再将事务 Proposal 操作的数据同步到所有 Follower(数据广播/数据复制)。
Zookeeper 采用 Zab 协议的核心就是只要有一台服务器提交了 Proposal,就要确保所有服务器最终都能正确提交 Proposal,这也是 CAP/BASE 最终实现一致性的体现。
2. ZAB 两种模式
ZAB 协议有两种模式:一种是消息广播模式,另一种是崩溃恢复模式。
1)消息广播模式
在系统正常运行时,Zookeeper 集群中数据副本的传递策略就是采用消息广播模式,Zookeeper 中的数据副本同步方式与2PC方式相似但却不同,2PC是要求协调者必须等待所有参与者全部反馈ACK确认消息后,再发送 commit 消息,要求所有参与者要么全成功要么全失败,2PC方式会产生严重的阻塞问题。
而 Zookeeper 中 Leader 等待 Follower 的 ACK 反馈是指:只要半数以上的 Follower 成功反馈即可,不需要收到全部的 Follower 反馈。
如下图:
Zookeeper 中广播消息步骤:
- 客户端发起一个写操作请求
- Leader 服务器处理客户端请求后将请求转换为 Proposal,同时为每个 Proposal 分配一个全局唯一 ID,即 ZXID
- Leader 服务器与每个 Follower 之间都有一个队列,Leader 将消息发送到该队列
- Follower 机器从队列中取出消息处理完(写入本地事务日志中)后,向 Leader 服务器发送 ACK 确认
- Leader 服务器收到半数以上的 Follower 的 ACK 后,即认为可以发送 Commit
- Leader 向所有的 Follower 服务器发送 Commit 消息
补充说明:ZXID
类似于 RDBMS 中的事务ID,用于标识一个 Proposal ID,为了保证顺序性,ZXID 必须单调递增,因此 Zookeeper 使用一个 64 位的数来表示,高 32 位是 Leader 的 epoch(选举纪元),从 1 开始,每次选出新的 Leader,epoch 加 1,低 32 位为该 epoch 内的序号,每次 epoch 变化,都将低 32 位的序号重置,这样保证了 ZXID 的全局递增性。
2)崩溃恢复模式
一旦 Leader 服务器出现崩溃或者由于网络原因导致 Leader 服务器失去了与过半 Follower 的联系,那么就会进入崩溃恢复模式。
Zookeeper 集群中为保证任何进程能够顺序执行,只能是 Leader 服务器接收写请求,其他服务器接收到客户端的写请求,也会转发至 Leader 服务器进行处理。
Zab 协议崩溃恢复需满足以下2个请求:
- 确保已经被 Leader 提交的 proposal 必须最终被所有的 Follower 服务器提交
- 确保丢弃已经被 Leader 提出的但没有被提交的 Proposal
也就是新选举出来的 Leader 不能包含未提交的 Proposal,必须都是已经提交了的 Proposal 的 Follower 服务器节点,新选举出来的 Leader 节点中含有最高的 ZXID,所以,在 Leader 选举时,将 ZXID 作为每个 Follower 投票时的信息依据。这样做的好处是避免了 Leader 服务器检查 Proposal 的提交和丢弃工作。
3. Leader 选举
ZAB协议的选举过程主要发生在恢复模式中,一般在系统启动或者领导者节点故障时触发,主要分以下几步:
1)开始选举
每个节点首先投给自己一票,并将自己的编号和最后一条已经提交的事务的ZXID(Zookeeper Transaction ID,包含了事务的epoch和计数器)发送给其他所有节点,表示它推举自己成为领导者。
2)收集选票
接收到其他节点的投票信息后,每个节点会比较其他节点的ZXID和自己的ZXID。如果其他节点的ZXID更高(epoch或者计数器更大),或者ZXID相同但是节点编号更大,那么就会将票投给这个节点。
3)计票
每个节点收集到超过半数的投票(包括自己的)后,就会认为选举完成,选出的领导者就是得票最多的节点。如果有多个节点的票数相同,就选择ZXID最大的节点,如果还是相同,就选择节点编号最大的。(比较优先级:票数最多>ZXID最大>节点编号最大)
4)领导者确认
选举完成后,新的领导者会向所有节点发送领导者确认消息,其他节点收到确认消息后,会向领导者发送已经接受领导者的消息。
5)新领导者工作
当领导者收到大多数节点的确认消息时,就可以开始提供服务,处理客户端的请求,从而结束了选举过程。
总结:ZAB协议的选举过程是为了在领导者节点故障时快速选出新的领导者,恢复系统的正常运行,同时还确保了系统的一致性。
三、Raft协议和ZAB协议的区别
1. leader选举的区别
1) 选举触发条件
在Raft协议中,如果 Follower 在一段时间内没有收到 Leader 的心跳信息,就会主动进入候选人状态并启动新一轮选举,原因可能只是 Leader 节点繁忙而无法及时响应等情况。而在ZAB协议除了系统启动时,只有等到 Leader 故障,无法提供服务时才会进行选举。Raft更偏向于积极选举,只要有可能就尝试选举新的领导者,而ZAB更倾向于保持现状,只有在确定领导者无法提供服务时才触发选举。
2) 投票规则
Raft协议中,每个节点只能投票一次,并且投票给第一个请求投票的候选人。而在 ZAB 协议中,节点可能会改变自己的投票,投给 ZXID 更大的节点。所以 ZAB 不存在随机超时时间,虽然第一票都会投给自己,但后续如果发现其他节点的 ZXID 更大,就修改自己的选票。
3) 票数要求
在Raft 协议中,候选人在获得超过半数的投票后成为 Leader。在 ZAB 协议中,新的领导者被选出后,还需要得到超过半数的节点的确认才能开始工作。
4) 选举leader决定因素
在Raft协议中,选举过程严格按照轮次(任期)进行,每轮选举只能选出一位Leader,选出 Leader 很大程度取决于随机的超时时间和日志最新。而在 ZAB 协议中,选举的结果主要取决于节点的 ZXID 以及节点编号。ZXID最大的节点通常是最近处理过事务,日志较新。
简而言之,Raft协议更侧重于通过随机的超时时间和日志一致性来进行选举,而ZAB协议则通过ZXID(事务的处理顺序)和节点编号来选举出Leader。
2. 日志复制机制的区别
ZAB 协议 的日志复制机制中由于多了一个预提交步骤,因此相比 Raft 协议会有更高的延迟,特别是在高负载和大规模集群的情况下。Raft 通过简单的多数节点确认就可以完成日志提交,因此它通常具有更低的延迟。
3. 使用场景
1)Raft 协议
较低的延迟,适用于实时要求较高的应用。Raft是使用较为广泛的分布式协议,我们熟悉的etcd注册中心就采用了这个算法。Redis中Sentinel 系统选举领头Sentinel的方法也是采用了raft协议。
2)ZAB 的优势
更强的容错性,适用于对日志顺序和一致性有严格要求的场景,如 Zookeeper 提供的分布式协调服务。由于 ZAB 协议是为 Zookeeper 的需求量身定制的,其他系统可能更倾向于使用 Raft 或 Paxos 等更为通用和成熟的协议。
参考链接:
https://juejin.cn/post/7143541597165060109
https://juejin.cn/post/7001070049200963621
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)