分布式的共识算法
分布式系统的共识算法是指在分布式环境中多个节点就某些信息达成一致的算法。这些算法在分布式系统中至关重要,尤其是在容错和保证一致性方面。
Paxos 算法
Paxos 算法是一种经典的分布式共识算法,由 Leslie Lamport 在 1990 年代提出。它旨在解决分布式系统中多个节点就某些信息达成一致的问题,尤其是在存在网络分区或节点故障的情况下。Paxos 算法特别强调强一致性,即所有参与的节点最终都会同意同一个值。
Paxos 算法包括两个主要的角色:Proposer 和 Acceptor。此外,还有一种角色叫做 Learner,用于监听并记录共识的结果。以下是 Paxos 算法的基本步骤:
- Prepare 阶段:
- Proposer 选择一个提案编号 n,并向一组 Acceptor 发送一个 Prepare(n) 消息。
- Acceptor 收到 Prepare(n) 消息后,如果它尚未对编号大于等于 n 的提案做出承诺,它会回复一个 Promise 消息,其中包含它先前承诺过的最大编号的提案值(如果有的话)。
- Proposer 收集大多数 Acceptor 的 Promise 消息。
- Accept 阶段:
- Proposer 选择一个值 v(通常是它收到的 Promise 消息中最大的提案值,如果没有则可以自由选择),并发送一个 Accept(n, v) 消息给所有 Acceptor。
- Acceptor 收到 Accept(n, v) 消息后,如果它已经回复了 Prepare(n) 的 Promise 消息,它就会接受该提案并记录提案值 v。
- Proposer 收集大多数 Acceptor 的 Accept 消息。
- Learn 阶段:
- Learner 收集大多数 Acceptor 的 Accept 消息后,它会学习到提案值 v,并将其传播给所有参与者。
Raft 算法是一种分布式共识算法,由 Diego Ongaro 和 John Ousterhout 在 2014 年提出。它旨在简化分布式系统中多个节点就某些信息达成一致的过程,并且相比 Paxos 算法更加直观易懂。Raft 算法特别强调通过选举领导者来简化共识过程,并且易于理解和实现。
Raft 算法的基本原理
Raft 算法的核心在于通过选举领导者来简化共识过程。它包括三种节点状态:Follower、Candidate 和 Leader。以下是 Raft 算法的基本步骤:
- 选举领导者:
- 当 Follower 没有收到领导者的心跳消息或投票请求一段时间后,它会变成 Candidate 并开始选举过程。
- Candidate 会发送投票请求给其他节点,并给自己投一票。
- 如果 Candidate 收集到大多数节点的投票,它将成为 Leader。
- Leader 状态:
- Leader 定期发送心跳消息给其他节点,以保持其领导地位。
- 当 Leader 收到客户端的请求时,它将请求添加到日志中,并将请求发送给其他节点。
- 当大多数节点记录了相同的日志条目后,Leader 认为该条目已经被提交,并将提交信息发送给其他节点。
- Follower 状态:
- Follower 节点接收来自 Leader 的命令和心跳消息。
- 如果长时间没有接收到任何消息,Follower 会变成 Candidate 并发起新的选举。
Nacos中使用了Raft算法来保证服务注册与发现的一致性。
ZAB 算法
ZAB 算法是 专为 ZooKeeper 设计的一种分布式共识协议
ZAB的选举机制的大致过程:
- 初始化: 当 ZooKeeper 集群启动时,每个节点都会初始化自己的轮次号为 0。
- 选举开始:
- 当前领导者失败或无法响应客户端请求。
- 所有节点检测到领导者失败,并进入
LOOKING
状态。并将自己的轮次号增加1。
- 发送选举请求:
- 每个处于
LOOKING
状态的节点都会向集群中的所有节点发送一个选举请求消息。 - 消息包含自己的节点ID和轮次号。
- 节点在发送选举请求时,会将自己的轮次号加 1,例如从 0 加到 1。
- 每个处于
- 投票:
- 每个节点收到选举请求后,会检查自己的投票记录。
- 如果还没有投票或者认为当前的候选者更好,则投票给这个候选者,并将投票信息发送回候选者。
- 节点在投票时,会比较候选者的轮次号和自己记录的轮次号。如果候选者的轮次号更高,节点会投票给这个候选者;如果轮次号相同,则根据节点ID来决定。(会投票给节点ID更低的节点,节点ID一般是按照节点的加入顺序分配的,越早加入的节点会获得更低的节点ID)
- 成为领导者:
- 当一个候选者获得集群中超过半数节点的投票时,它成为新的领导者。
- 成为领导者后,该节点会将自己的状态设置为
LEADING
,并且将自己的轮次号作为当前的领导者轮次号。
- 通知其他节点:
- 领导者向集群中的所有其他节点发送消息,通知它们自己已成为领导者。
- 其他节点收到消息后,将自己的状态设置为
FOLLOWING
。 - 其他节点也会更新自己的轮次号为领导者轮次号。