更新并阅读Cassandra的计数器,正确的方法是什么?

时间:2016-01-13 12:31:27

标签: cassandra-2.0 datastax

在Cassandra中读取更新计数器值的最佳方法是什么?让我们说从我的应用程序中我需要更新一个计数器,然后使用它的更新值。所以我有两个查询,第一个更新计数器,下一个读取它。据我所知,由于数据的复制,无法保证读取查询将获得更新的计数器。所以我可以看到有两种方法:

  1. 使用一致性级别ALL更新计数器,然后读取它。我不确定此操作的性能影响是什么?

  2. 在更新之前读取计数器值,然后更新它。然后将读取值增加1并使用它。现在我认为这种方法没有任何问题?

  3. 或者可能还有其他方法和其他一些我没有考虑的因素?

    无论如何,我很乐意找出最佳做法是什么?

2 个答案:

答案 0 :(得分:1)

  

据我所知,由于数据的复制,无法保证读取查询将获得更新的计数器。

问题更多的是关于计数器的分布式设计。请参阅以下时间表

初始计数器值= 0

  1. T1。客户端A递增计数器+5
  2. T2。客户B增加计数器+3
  3. 如果客户A在 t2之前读回计数器值,它将看到counter = 5

    如果客户A在 t2之后回读计数器值,它将看到counter = 8(+5 +3)

    如果您在读回计数器值时,其他人已更新或不更新,那么您现在不能。使用轻量级事务(LWT)使计数器更新可线性化不是一个选项,因为计数器表不支持LWT。

    也许您应该描述一下您的用例,以便我们能够设计出合适的方法。你想用柜台做什么?您希望创建什么类型的查询以读取您的计数器?

答案 1 :(得分:1)

正如@doanduyhai解释的那样,当并发客户端同时增加计数器时,两种方法都容易出错。 这是我们设计上的问题,我们使用一个计数器表作为其他表的键,因此我们需要唯一的ID。是的,我们知道我们可以使用UUID作为唯一ID,但是我们希望保持键的排序并易于在客户端读取。 我们的解决方案:

v1 =读取计数器A。

-增加计数器A。

v2 =再次读取计数器A。

如果v2 == v1 + 1,则该过程是单独的还是第一个,请使用计数器并忘记。

如果不是,则表明存在多个进程竞争的信号,因此:

随机睡眠(因此每个进程睡眠不同的时间,并且不会永远竞争),然后重试整个循环。