networking - Raft 如何处理长时间的网络分区?

标签 networking distributed consensus raft

考虑我们在 3 台机器上运行 Raft:A、B、C,并让 A 成为领导者。存在一个网络分区,将 C、A、B 分开。将当前项称为 t。 A 和 B 保持在第 2 期,除了定期心跳之外没有其他消息。此时C进入候选状态,并将term递增到3,为自己投票,超时,重复。比如说 10 个周期后,网络分区就解决了。现在状态是A[2],B[2],C[12]; C 将拒绝来自 A 的 AppendEntries RPC,因为第 2 项小于其当前项 10; C 无法达到法定人数,并将继续作为候选人运行领导者选举协议(protocol),并且与 A 和 B 当前的任期值越来越背离。

那么问题是,Raft(或 Raft 派生的实现)如何处理这个问题?我的一些想法包括:

  1. 这种情况是可用性问题,而不是安全违规。忽略并让人类运算符(operator)通过杀死或重置 C 来处理
  2. 指数退避以减少每次选举 C 的分歧
  3. 让 C 使用lastApplied 而不是currentTerm 作为拒绝或接受AppendEntries RPC 的基础。也就是说,我们相信日志是术语的真实来源,而不是 currentTerm 值。这已经被用来确保 C 不会根据选举限制获胜,但是该文件似乎表明这个“最新”属性是不投票给 C 的理由,但不是 C 默许的理由并重置为关注者。

注意:术语按照寻找可理解的共识算法(扩展版本)

最佳答案

当 C 拒绝来自领导者 A 的 AppendEntries RPC 时,它将返回现在的 > 2 项。 Raft 副本总是识别更大的术语,因此反过来会导致领导者下台并开始新的选举。最终,集群将收敛到一个新项,即 > 2,即 >= C 项。

这是一个经常讨论的(在 Raft 开发社区中)有点不方便的场景,可能会导致 Raft 集群中不必要的流失。为了防范这种情况,Raft 论文以及大多数现实世界的实现引入并使用了所谓的“预投票协议(protocol)”。预投票协议(protocol)本质上规定,在成为候选人之前,追随者必须首先通过询问其同伴来确定它是否可以赢得选举。在上面描述的场景中,C 会要求 A 和 B 进行预投票,但由于网络分区,它不会收到任何投票。因此,C 永远不会转换为候选角色,永远不会增加术语,因此在分区修复后永远不会出现术语 > 2。因此,您已经消除了客户流失。

您可以在迭戈的论文中阅读有关预投票协议(protocol)的更多信息。

关于networking - Raft 如何处理长时间的网络分区?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70674872/

相关文章:

android - 在文件上传过程中显示进度条

distributed-computing - 分布式系统是什么意思?

python - Dask Distributed 在compute()期间似乎没有传递请求的操作

java - 最佳实践 : network communication

javascript - 联网框架动态房间不能使用简单的 rtc

sockets - 在 go 中不阅读而窥视 Conn

python - Dask分布式: How to computationally recognize if worker is idling?

distributed-system - 领导选举的 paxos vs raft

java - 使用 FIFO 队列和 peek() 方法实现共识协议(protocol)

networking - configtx.yaml 中的每个定义在 Hyperledger fabric v1.0 中意味着什么?