raft 算法如何在写入失败后节点失败的情况下保持强读取一致性

ris*_*tal 1 consensus raft

考虑三个节点(A、B、C)获取键/值数据。并且发生了以下步骤

  1. 节点 A 接收键:值 (1:15)。它是一个领导者
  2. 它复制到节点 B 和节点 C
  3. 在预提交日志中对节点 B 进行的条目
  4. 节点 C 登录失败
  5. 来自节点 B 的 Ack 丢失。
  6. Nod A 输入失败并发送失败给客户端
  7. 节点 A 仍然是领导者,而 B 不在法定人数中
  8. 客户端从节点 A 读取键 1 并返回旧值。
  9. 节点 A 已关闭
  10. 节点 B 和节点 C 已启动
  11. 现在节点 B 在预提交日志中有一个条目,而节点 C 没有。

此时日志匹配如何发生。节点 B 是要提交该条目还是要丢弃它。如果它要提交,那么它会被读取不一致,或者如果它要丢弃,那么在其他情况下可能会丢失数据

rys*_*sov 6

错误在第 8 步。每个读取操作都必须复制到其他节点,否则您可能会获得过时的数据,系统应该在将虚拟值写入日志后提供读取服务。在您的情况下(B离线),“读取”必须影响节点AC,因此当节点B重新联机并A死亡时,C将能够使B的记录无效。

这是一个棘手的问题,甚至 Etcd 过去也遇到过(现在已修复)。