首页 > 解决方案 > 为什么在使用基于仲裁的读写时Cassandra不能线性化

问题描述

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

线性化定义为

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

标签: databasecassandra

解决方案


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

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

在此处输入图像描述

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

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

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

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

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

从 Martin Klepmann 的 Data Intensive Applications 一书中复制

线性化和仲裁 直观地说,似乎严格的仲裁读取和写入在 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 风格的 quorums 线性化:读取器必须在将结果返回到应用程序 [23] 之前同步执行读取修复(参见第 178 页的“读取修复和反熵”),并且写入者必须在发送其写入之前读取法定节点的最新状态 [24, 25]。然而,由于性能损失 [26],Riak 不执行同步读取修复。Cassandra 确实在仲裁读取 [27] 上等待读取修复完成,但如果对同一个键有多个并发写入,它就会失去线性化,因为它使用了最后写入胜出的冲突解决方案。

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

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

还有更多关于线性化与序列化的解释:

在此处输入图像描述


推荐阅读