卡桑德拉:旋转名单

时间:2013-03-20 19:07:11

标签: cassandra

假设我在Cassandra行中存储事件列表,使用复合列实现:

{
    event:123 => 'something happened'
    event:234 => 'something else happened'
}

这对我来说几乎没问题,据我所知,这是一种常见的模式。与具有jsonized列表的单个列event相比,它可以更好地扩展,因为很容易将新项添加到列表中而不先读取它然后再写回来。

但是,现在我需要实现这两个要求:

  • 如果最后添加的事件相同,我不想添加新事件
  • 我想只留下N个最后的事件。

是否有任何标准方法可以实现最佳性能? (任何存储架构更改都可以。)

1 个答案:

答案 0 :(得分:2)

检查事物是否已经存在,或者检查存在的数量以及删除多余的项目,都是读取 - 修改 - 写入操作,并且它们不能很好地适应Cassandra的约束。

仅保留N个最后事件的一种方法是确保它们是有序的,以便您可以进行范围查询并读取N last(例如,使用时间戳/ TimeUUID为列键添加前缀)。这不会删除过时的事件,您需要将其作为一个单独的进程来执行,但通过这样做,查询数据的代码只会看到最后的N,这是我正确解释事物的真正要求。旧事件的垃圾收集只是一种优化,以避免保留永远不会再需要的东西。

如果要求不是严格的N事件,但事件不是T,你当然可以使用TTL功能,但我认为它不是你的选择。

第一个要求比较棘手。你可以在写之前做一个阅读并检查你是否有一个项目,但这会很慢,除非你在Cassandra之外做某种锁定,否则无法保证两个作者不会同时做两个读取然后两者都写,所以既不会看到对方的写。也许这对你来说不是问题,但是没有好办法解决它。卡桑德拉不做CAS。

我在使用Cassandra时处理类似情况的方法是在应用程序节点中保留已写入的内容,并在写入之前检查。然后,您需要确保每个应用程序节点都看到同一行的所有事件,并且同一行的事件不会分布在多个应用程序节点上。一种方法是在应用程序节点前面建立一个消息队列系统,并使用与数据库中的行键相同的密钥将事件流划分为多个队列。