在“设计数据密集型应用程序。可靠、可扩展和可维护系统背后的大创意”一书中,我们可以阅读有关草率仲裁的信息:
但是,这意味着即使当w + r > n时,你也不能确定读取到某个key的最新值,因为最新值可能已经被临时写入了n之外的某些节点
但我似乎无法理解这背后的含义。
让我们举一个客户端为键“K1”写入不同值的示例。
假设我们有:
我们有W+R>N。
假设我们已经有了 A、B 和 C 中“K1”的第一个值:(K1,V1)
然后假设节点 A 和 B 发生故障,然后客户端在 Sloppy Quorum 配置中写入 (K1,V2)。
我的理解是,我们将使用节点 C、D 和 E 进行写入和复制(K1、V2),以避免像严格仲裁配置中那样阻塞写入操作,并且我们需要其中两个节点的确认。假设我们收到了 C 和 D 的确认,因此写入成功。
现在另一个客户端想要读取 K1 的值,它需要两个响应,我们有三种可能性:
因此,我想说,我们的 Sloppy Quorum 系统可以保证强读取一致性(只要它处理冲突,这也是在 Strict Quorum 配置中应该处理的事情),因为返回值将是 (K1,V2) ),这似乎不是书上解释的。
这个推理有什么问题吗?
经过一些研究和分析,我想我明白了作者的意思。
问题中的推理是正确的,但不完整:
第二个客户端获取值(K1,V2)后,假设节点A和B恢复。
通常,由于我们处于 Sloppy Quorum 配置中,因此会有一个提示切换阶段,其中节点 D 和 E 在恢复后将最近的数据发送回 A 和 B。我们可以在书上读到:
一旦网络中断被修复,任何一个节点的写入 暂时接受代表另一个节点被发送到 适当的“主”节点。这称为提示切换。
我们的 Sloppy Quorum 配置的问题是,如果另一个客户端想要在节点 A 和 B 恢复后、但在提示切换开始之前读取 K1 的值,则该客户端可能会收到来自 A 和 B 的两个响应与旧值(K1,V1),并且客户端将接受该值,因为R=2。所以在这种情况下客户端将无法获得最新值,正如书中所解释的那样。
只有在提示切换完成后,客户端才能安全地获取最新值(K1,V2),正如作者所解释的:
因此,草率的法定人数实际上根本不是法定人数 传统意义上。这只是耐久性的保证,即 数据存储在某处的 w 个节点上。无法保证 r 节点的读取将看到它,直到暗示的切换完成。
那么“Sloppy Quorum 能否保证强读一致性?”这个问题的答案会是:不。