【发布时间】:2019-11-09 17:22:07
【问题描述】:
您能否解释一下为什么即使使用基于仲裁的读写,Cassandra 也不能线性化?
线性化定义为
如果操作 B 在操作 A 成功完成后开始,则操作 B 必须看到系统处于与操作 A 完成时相同的状态,或者更新的状态。
【问题讨论】:
您能否解释一下为什么即使使用基于仲裁的读写,Cassandra 也不能线性化?
线性化定义为
如果操作 B 在操作 A 成功完成后开始,则操作 B 必须看到系统处于与操作 A 完成时相同的状态,或者更新的状态。
【问题讨论】:
考虑 Cassandra 前台读取修复进行编辑:
由于仅更新部分副本集而失败的写入可能会导致两个不同的读取器看到两个不同的数据值。这是因为在简单的基于仲裁的一致性方法中缺乏回滚。这种行为打破了单键读取的线性化保证。正如discussion 中所述,Raft 或 Paxos 等分布式共识协议是此类保证的必备条件。
此外,clock drift 和 leap second 等其他现象可能会破坏 Cassandra 会话的一致性。
早期答案(不考虑 Cassandra 前台读取修复):
总结: 在 Cassandra 中编写可能感觉不到原子性。一些节点的写入速度比其他节点快,因此即使我们依赖 quorum,结果也取决于返回值的节点集以及它们当时持有的值。
另外,解释线性化的定义添加到粗体定义
如果操作 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 风格的 quorums 线性化:读取器必须在将结果返回到应用程序之前同步执行读取修复(参见第 178 页的“读取修复和反熵”)[23 ],并且写入者必须在发送其写入之前读取节点法定人数的最新状态 [24, 25]。然而,由于性能损失 [26],Riak 不执行同步读取修复。 Cassandra 确实在仲裁读取 [27] 上等待读取修复完成,但如果有多个并发写入同一个键,它会失去线性化,因为它使用了最后写入胜出冲突解决方案。
而且,这种方式只能实现可线性化的读写操作;线性化的比较和设置操作不能,因为它需要一个共识算法 [28]。
总之,假设具有 Dynamo 式复制的无领导系统不提供线性化是最安全的。
还有一点关于线性化与序列化的解释:
【讨论】:
编辑:事后看来,这不是最好的解释。我建议阅读下面更简洁的 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 的角度来看,操作 B 并没有有效地“看到”A,因为它没有考虑数据的现有状态或可能发生的任何其他操作。在提交B 期间,另一个客户可能正在更新同一帐户的余额。
Lightweight Transactions in Cassandra 2.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 protocol 进行领导选举并确保按顺序应用操作。如果余额状态不满足条件,则不会应用更新(通过was_applied 布尔列指示成功响应)。如果 C* 在某个超时时间内(由于争用或其他一些因素)无法实现这一点,则操作将失败,将不会被应用,并且客户端将出现超时。
【讨论】: