假设仲裁系统有 5 个节点,写入和读取仲裁数为 3。现在,假设客户端发送写入请求 w,并且 w 被复制到 2/5 个节点上。由于我们没有在至少 3/5 的节点上进行复制,因此我们告诉客户端写入不成功。现在,紧接着,未复制写入的 2 个节点出现故障。因此,在剩下的 3 个节点中,2 个有部分写入,1 个没有。在这种情况下,系统如何确定部分写入 w 需要撤消,因为它实际上并未成功完成?
在大多数系统中,3/5 表示该值已被选择且不得撤消。
不同的协议和系统以不同的方式处理这个问题。
在 ABD 中,下一个 read 将从一个节点学习值 和 并将其传播到其他两个剩余节点。
类似地,在Paxos中,下一个提议者将从该一个节点学习值并将其传播到其他两个节点。在基于 Paxos 的实际系统中,会有一个系统(可能是 Leader)会产生一个“no-op”提案,以确保价值及时传播。 在像
Raft这样的领导者选举/主副本系统中,领导者将确保传播到副本。当然,除非它是死者之一。在这种情况下,选举过程通常要求新领导者是最新的,在这种情况下将包括有争议的值。
领导者有责任确保事件成功发送到事件被视为已提交之前定义的最小法定人数[应该有一个带有该事件 ID 的哈希码的标志],并且该事件没有资格重试。
当请求进入图片以从分布式系统获取数据时;它总是发送给领导者,领导者将通过哈希码将请求委托给附近的节点。但在委托之前,Leader 必须确保 Commit Flag 为 TRUE(意味着事件被传递到最少定义的节点)。否则,Leader 可以抛出异常。
此外,Leader 应在事件中标记版本号,并保留当前提交的标志版本号。在检索事件时,Leader 可以比较事件版本,以确保所有节点都提供最新和最好的数据。
您可以从 Zookeeper 等系统中看到开箱即用的功能。
读取器处理混乱。 您发现的问题是没有明显多数。如果其他三个没有得到复制的人能够回复的话,那就没有问题了;部分写入将被下一个读者忽略。
大多数系统都倾向于“读修复”;也就是说,读者在发现没有明显多数的情况下,将所选的写入传播给尚未收到该写入的其他人。 (是的,在这种情况下,读取会导致内部写入的损失)。为了确定要传播哪个值,系统需要知道如何打破平局。通常会比较时间戳和日志偏移量来确定哪个值是最新的并传播它。 Cassandra 使用“最后写入者获胜”协议。
某些系统(例如 Raft)可以根据情况传播或撤消部分写入。在这里,正常情况下,领导者会不断地将其日志传播给所有追随者。然而,在某些情况下,另一个领导者被选举出来,然后将自己的意愿强加给其追随者,并在此过程中覆盖早期读者的一些部分写入。