以原子方式更新Cassandra中的共享状态

时间:2013-02-17 03:13:17

标签: nosql cassandra

问题:

我打算将cassandra用作我的应用程序的nosql数据存储。我有一个使用案例是更新用户的“余额”。假设每个用户的余额存储为密钥UID_balance。现在,如果我的应用程序想要更新多个用户的余额,我将如何处理原子性?

我想,在某些时候,应用程序基本上会执行以下操作:

1. for each user u
2.    current_balance = read_users_balance(u);
3.    new_balance     = current_balance + delta_for_user(u);
4.    write_users_balance(u, new_balance);
5. end

现在,这里有几个问题:

  1. 与cassandra的连接可能会中断,导致代码只更新少数用户的余额。
  2. 在第2步和第4步之间,可能有另一个进程可以更新用户的余额,我将更新陈旧的余额,使用户的余额处于“损坏”状态。
  3. RDBMS'解决了这些问题,因为它们提供ACID属性,而Cassandra则没有。我最近看到Cassandra(2012年10月)已经开始提供Atomic Batches。我不确定这是否是解决这个问题的正确方法。

    可能的解决方案:

    这是我和朋友一起集思广益的事情。我们实际上并不更新用户的余额,而是创建一条记录,将更新增量附加到不同的记录。例如:

    UID1_balance = {100}
    UID1_deltas  = {10,20,-40}
    

    为了获得当前余额,我们只需将增量应用于余额。我们可以有一个离线流程,将增量应用于用户的余额并修剪增量列表。

    这个解决方案起作用并降低了腐败状态的可能性,但我认为这是一种矫枉过正。有没有更好的方法来解决这个问题?

3 个答案:

答案 0 :(得分:6)

我建议阅读论文“建立在流沙上”这会让你考虑到帐户,他们甚至会参考像这样的银行帐户示例。注意:Chase和well fargo不会在交易中转账,因此他在那篇文章中解释了我们如何在微观层面上做同样的事情,就像宏观层面一样;)。

这也有助于PlayOrm for cassandra的编写,因为PlayOrm维基上也有一个模式页面。

答案 1 :(得分:2)

由于没有锁定,因此无法在Cassandra中使用您的初始“读取修改写入”方法。 Cassandra计数器部分解决了这个问题,但在两个地方达不到要求:

  1. 您不能使用多个计数器进行原子批处理,这意味着最终可能会应用某些更新,而其他更新则不会。
  2. 如果出现错误,您无法判断计数器是否已增加,因此最终可能会出现不准确的值。
  3. 这意味着将增量存储为单独列的可能解决方案是获得所需保证的唯一方法,与Cassandra 1.2中的原子批次相结合(请参阅http://www.datastax.com/dev/blog/atomic-batches-in-cassandra-1-2)。您的解决方案就像实现计数器一样,每个计数器都在一行中,每个delta都是一列。要阅读,请总结一行中列的所有值。

    正如你所说,这里的问题是处理垃圾,因为这些增量列表会随着时间的推移而增长。如果没有太多更新可以,但如果经常更新余额,那么阅读速度会太慢。

    通过读取增量然后以原子方式删除它们并为整个值添加一个增量,可以使“垃圾收集”的离线过程安全。使用原子批次和单线程进程可以确保安全。

答案 2 :(得分:2)

  1. 正如理查德指出的那样,目前最好的方法是使用原子批次来更新许多增量。如果出现问题,只需重播批次。

  2. 另一种可能的解决方案是使用ZooKeeper作为协调和分布式锁定服务:http://ria101.wordpress.com/tag/zookeeper/

  3. 另一种可能的解决方案是使用counters,因此您不需要这样做

    your current_balance = read_users_balance(u);
    new_balance     = current_balance + delta_for_user(u);
    

    因为使用计数器,您不需要在更新前阅读余额。 http://www.datastax.com/dev/blog/whats-new-in-cassandra-0-8-part-2-counters

  4. 然而,计数器存在问题,它们不是幂等的,因此如果您没有收到确认您的增量/减量成功,则无法重播该计数器,因为它可能导致计数过多。

    新计数器将解决problem