为什么在使用基于仲裁的读写时 Cassandra 不可线性化

Anu*_*rma 8 database cassandra

您能否解释为什么即使使用基于仲裁的读写,Cassandra 也不能线性化?

线性化定义为

如果操作 B 在操作 A 成功完成后开始,则操作 B 必须看到系统处于与操作 A 完成时相同的状态,或更新的状态。

Anu*_*rma 9

编辑考虑 Cassandra 前景读取修复:

由于仅更新了部分副本而失败的写入可能会导致两个不同的读取器看到两个不同的数据值。这是因为在简单的基于仲裁的一致性方法中缺乏回滚。这种行为破坏了单键读取的线性化保证。如本次讨论中所述,Raft 或 Paxos 等分布式共识协议是此类保证的必备条件。

在此处输入图片说明

此外,时钟漂移闰秒等其他现象可能会破坏 Cassandra 会话的一致性。

较早的答案(不考虑 Cassandra 前台读取修复):

总结:在 Cassandra 中写入可能没有原子性。一些节点的写入速度比其他节点快,因此即使我们依赖仲裁,结果也取决于返回值的节点集以及它们在该点持有的值。

此外,为了解释线性化的定义,添加到粗体的定义

如果操作 B 在操作 A 成功完成后开始,则操作 B 必须看到系统处于与操作 A 完成时相同的状态,或者更新的状态(但不再是旧状态)

从 Martin Klepmann 的《数据密集型应用程序》一书中复制

可线性化和仲裁 直觉上,严格的仲裁读取和写入似乎应该在 Dynamo 风格的模型中线性化。然而,当我们有可变的网络延迟时,就有可能出现竞争条件,如图 9-6 所示。

在此处输入图片说明

在图 9-6 中,x 的初始值为 0,并且写入客户端通过将写入发送到所有三个副本(n = 3,w = 3)来将 x 更新为 1。同时,客户端 A 从两个节点 (r = 2) 的仲裁中读取,并在其中一个节点上看到新值 1。同样在写入的同时,客户端 B 从两个节点的不同仲裁读取,并从两个节点取回旧值 0。

满足法定人数条件 (w + r > n),但此执行仍然不可线性化:B 的请求在 A 的请求完成后开始,但 B 返回旧值而 A 返回新值。(这又是图 9-1 中 Alice 和 Bob 的情况。)

有趣的是,有可能以降低性能为代价使 Dynamo 风格的仲裁线性化:在将结果返回给应用程序 [23] 之前,读取器必须同步执行读取修复(请参阅第 178 页的“读取修复和反熵”),并且写入者必须在发送其写入之前读取法定节点的最新状态 [24, 25]。然而,由于性能损失,Riak 不执行同步读取修复 [26]。Cassandra 确实会在仲裁读取 [27] 上等待读取修复完成,但是如果对同一个键有多个并发写入,它会失去线性化能力,因为它使用了最后写入获胜的冲突解决方案。

而且这种方式只能实现线性化的读写操作;线性化的比较和设置操作不能,因为它需要一个共识算法[28]。

总之,假设具有 Dynamo 式复制的无领导系统不提供线性化是最安全的。

关于线性化与可串行化的更多解释:

在此处输入图片说明