假设我在Cassandra行中存储事件列表,使用复合列实现:
{
event:123 => 'something happened'
event:234 => 'something else happened'
}
这对我来说几乎没问题,据我所知,这是一种常见的模式。与具有jsonized列表的单个列event
相比,它可以更好地扩展,因为很容易将新项添加到列表中而不先读取它然后再写回来。
但是,现在我需要实现这两个要求:
是否有任何标准方法可以实现最佳性能? (任何存储架构更改都可以。)
答案 0 :(得分:2)
检查事物是否已经存在,或者检查存在的数量以及删除多余的项目,都是读取 - 修改 - 写入操作,并且它们不能很好地适应Cassandra的约束。
仅保留N个最后事件的一种方法是确保它们是有序的,以便您可以进行范围查询并读取N last(例如,使用时间戳/ TimeUUID为列键添加前缀)。这不会删除过时的事件,您需要将其作为一个单独的进程来执行,但通过这样做,查询数据的代码只会看到最后的N,这是我正确解释事物的真正要求。旧事件的垃圾收集只是一种优化,以避免保留永远不会再需要的东西。
如果要求不是严格的N事件,但事件不是T,你当然可以使用TTL功能,但我认为它不是你的选择。
第一个要求比较棘手。你可以在写之前做一个阅读并检查你是否有一个项目,但这会很慢,除非你在Cassandra之外做某种锁定,否则无法保证两个作者不会同时做两个读取然后两者都写,所以既不会看到对方的写。也许这对你来说不是问题,但是没有好办法解决它。卡桑德拉不做CAS。
我在使用Cassandra时处理类似情况的方法是在应用程序节点中保留已写入的内容,并在写入之前检查。然后,您需要确保每个应用程序节点都看到同一行的所有事件,并且同一行的事件不会分布在多个应用程序节点上。一种方法是在应用程序节点前面建立一个消息队列系统,并使用与数据库中的行键相同的密钥将事件流划分为多个队列。