CQL3“IF”是否使我的更新不是幂等的?

时间:2015-12-26 03:07:08

标签: cassandra cassandra-2.1 cassandra-3.0 cassandra-2.2

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

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

Cassandra更新的最佳实践是使更新具有幂等性,但IF运营商与此直接对立。我错过了什么吗?

2 个答案:

答案 0 :(得分:2)

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

例如,假设您的客户端正在聚合某些值并将结果写入汇总表。每个客户端都会计算相同的总数并写入相同的值,因此,如果多个客户端写入它或者写入它的顺序不重要,因为它将是相同的值。

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

但是,在没有相互排斥的情况下执行此操作的另一种方法是将每个提款和存款写为单独的聚集事务行,然后将余额计算为应用所有事务行的幂等结果。

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

答案 1 :(得分:1)

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

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