为什么使用基于仲裁的读写时cassandra不能线性化

ruoxqz4g  于 2021-06-14  发布在  Cassandra
关注(0)|答案(3)|浏览(414)

您能解释一下为什么即使使用基于仲裁的读写操作,cassandra也不能线性化吗?
线性化定义为
如果操作b是在操作a成功完成之后启动的,则操作b必须看到系统处于与操作a完成时相同的状态,或者处于较新的状态。

zlwx9yxi

zlwx9yxi1#

编辑:事后看来,这不是最好的解释。我建议阅读下面的anurag的答案,它要简洁得多。
由于正常的cassandra操作不会观察到它正在改变的现有状态,因此仅仲裁一致性不被认为是“可线性化的”。
例如,如果您要调整银行账户的余额,您需要知道当前余额才能进行调整。考虑执行以下操作的客户端:

A. SELECT balance FROM account WHERE id='x' (assume this returns 5.12)
B. UPDATE account SET balance=4.12 WHERE id='x' (subtract 1$ from balance)

问题是,从Cassandra的Angular 来看 B 不能有效地“看见” A 因为它不考虑数据的现有状态或可能发生的任何其他操作。另一个客户可能在提交数据期间更新同一账户的余额 B .
cassandra2.0中的轻量级事务描述了轻量级事务如何通过提供结构来提供“线性化一致性”,这些结构可以确保对给定分区按顺序执行操作,并且不会被其他分区中断。因此,与我前面的示例不同,您现在可以执行以下操作:

A. SELECT balance FROM account WHERE id='x' (assume this returns 5.12)
B. UPDATE account SET balance=4.12 WHERE id='x' IF balance=5.12

使用 IF balance=5.12 指示cassandra开始一个轻量级事务,该事务使用paxos consesus协议进行领导层选举,并确保按顺序应用操作。如果平衡状态不满足条件,则不会应用更新(在带有 was_applied 布尔列)。如果c*无法在某个超时时间内实现这一点(由于争用或其他一些因素),则操作将失败,不会应用,并且客户端将显示一个超时时间。

nlejzf6q

nlejzf6q2#

小结:在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中爱丽丝和鲍勃的情形。)
有趣的是,可以以降低性能为代价使dynamo风格的量子数线性化:在将结果返回给应用程序[23]之前,读取器必须同步执行读修复(参见第178页的“读修复和反熵”),并且写入器必须在发送其写操作[24, 25]. 但是,由于性能损失,riak不执行同步读取修复[26]。cassandra确实在仲裁读取[27]时等待读取修复完成,但如果对同一个密钥有多个并发写入,则它将失去线性化能力,因为它使用了last write wins conflict resolution。
此外,以这种方式只能实现线性化的读写操作;可线性化的比较和设置操作无法实现,因为它需要一致性算法[28]。
总之,最安全的假设是带有dynamo风格复制的无领导系统不提供线性化能力。
关于线性化和串行化的更多解释:

t0ybt7op

t0ybt7op3#

根据您的定义,当cassandra的读写设置设置为quorum时,它是可以线性化的。
关于序列一致性的旧文档
然而,似乎无条件更新是什么'打破'线性化和那些需要被禁用的驱动程序级别Cassandra被标记为'线性化'。
因此,可以用cassandra实现线性化。但Cassandra本身不会强制执行线性化。

相关问题