1

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

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

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

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

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

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

4

1 回答 1

2

检查事物是否已经存在,或者检查存在多少并删除额外的项目,都是读-修改-写操作,它们不太适合 Cassandra 的约束。

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

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

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

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

于 2013-03-20T20:12:47.413 回答