【发布时间】:2019-06-16 01:28:44
【问题描述】:
在实现 Raft 算法时,我发现有一种情况我认为可能对集群造成伤害,也可能不会。
假设一些来自 Leader 的 AppendEntriesRPC 被重新排序(网络延迟或其他原因)是合理的。考虑领导者使用prev_log_index = 1向对等点A发送心跳AppendEntriesRPC,然后发送另一个带有条目2的AppendEntriesRPC,然后它崩溃(我通过我的测试中的回调确保这立即发生)。如果两个 RPC 按发送顺序处理,则条目 2 将成功插入。但是,如果心跳 RPC 延迟,那么 peer A 会首先插入 entry 1 并响应 Leader。然后是延迟的心跳,peer A 将删除条目 2,因为该条目与 Leader 的prev_log_index = 1 冲突。所以对等体 A 错误地删除了一个日志条目。
再深入一点,如果Leader没有立即崩溃,它会解决这个问题吗?我认为如果 peer A 正确响应延迟的心跳,Leader 会在以后的一些 RPC 中发现并修复它。
但是,如果对等体 A 对条目 2 的响应导致 commit_index 前进怎么办?在这种情况下,节点 A 投票将 commit_index 推进到 2,即使它实际上没有条目 2。因此可能没有足够的票数来推进这一推进。现在当Leader崩溃时,日志较少的节点将被选为Leader。我在测试过程中确实遇到过这种情况。
我的问题是:
- 我的推理正确吗?
- 如果重新排序 RPC 是一个真正的问题,我应该如何解决?对所有 RPC 进行索引和缓存,并强制它们一一处理是一个好的解决方案吗?我发现在 gRPC 中很难实现。
【问题讨论】:
标签: distributed-computing distributed-system consensus raft