0

在我看来,如果重试,使用 IF 会使语句可能失败。因此,该语句不是幂等的。例如,给定下面的 CQL,如果它由于超时或系统问题而失败并且我重试它,那么它可能无法工作,因为另一个人可能在重试之间更新了版本。

UPDATE users
SET name = 'foo', version = 4
WHERE userid = 1
IF version = 3

Cassandra 中更新的最佳实践是使更新具有幂等性,但 IF 操作员直接反对这一点。我错过了什么吗?

4

2 回答 2

2

如果您的应用程序是幂等的,那么通常您不需要使用昂贵的 IF 子句,因为您的所有客户端都会尝试设置相同的值。

例如,假设您的客户正在聚合一些值并将结果写入汇总表。每个客户端将计算相同的总数并写入相同的值,因此多个客户端是否写入它,或者他们写入它的顺序无关紧要,因为它将是相同的值。

如果您实际上要寻找的是互斥,例如保持银行余额,则可以使用 IF 子句。您可能会读取一行以获取当前余额,然后减去一些钱并仅在您读取后余额没有改变的情况下更新余额。如果另一个客户同时尝试添加存款,那么它将失败并且必须重试。

但另一种不互斥的方法是将每个取款和存款写入单独的集群交易行,然后将余额计算为应用所有交易行的幂等结果。

您可以将 IF 子句用于幂等写入,但这似乎毫无意义。第一个执行写入的客户端将成功,Cassandra 将返回值“applied=True”。下一个尝试相同写入的客户端将返回“applied=False, version=4”,表明该行已经更新到版本 4,因此没有任何更改。

于 2015-12-26T21:27:59.877 回答
1

这个问题更多的是关于线性化(排序)而不是我认为的幂等性。此查询使用 Paxos 在应用更改之前尝试确定系统的状态。如果系统的状态相同,则可以多次重试查询而不改变结果。与大多数 Cassandra 所写的不同,这提供了一种弱形式的排序(而且很昂贵)。通常,如果您尝试记录系统状态(而不是历史记录或日志),则应仅使用 CAS 操作

如果您能提供帮助,请不要使用其中的许多查询,指南建议您的查询中只有一小部分依赖于这种行为。

于 2015-12-26T03:57:01.460 回答