新闻提要,例如 cassandra 上的时间序列数据

news feed like time-series data on cassandra

我正在制作一个网站,我想将所有用户 post 存储在一个 table 中,按他们 post 的时间排序。我做的cassandra数据模型是这个

CREATE TABLE Posts(
   ID uuid,
   title text,
   insertedTime timestamp,
   postHour int,
   contentURL text,
   userID text,
   PRIMARY KEY (postHour, insertedTime)
) WITH CLUSTERING ORDER BY (insertedTime DESC);

我面临的问题是,当用户访问 posts 页面时,它通过查询

获取最新的页面
SELECT * FROM Posts WHERE postHour = ?;

? = 当前时间

到目前为止,当用户向下滚动时 ajax 请求从服务器获取更多 post。 Javascript 跟踪 lastFetched 项目的 post 小时,并在请求新的 posts 时与 cassandra PagingState 一起发回服务器。

但是当用户向下滚动时,这种方法将查询超过 1 个分区。 我想知道这个模型是否可以毫无问题地执行,是否有任何其他模型可以遵循。

有人请指点我正确的方向。 谢谢。

这是一个好的开始,但有几点建议:

  1. 您可能需要的不仅仅是 postHour 作为分区键。我猜您不希望将所有 post 不分日期 存储在一起,然后翻阅它们。你可能想看的是:

    PRIMARY KEY ((postYear, postMonth, postDay, postHour), insertedTime)
    
  2. 但是还是有问题。您的 PRIMARY KEY 必须唯一标识一行(在本例中为 post)。我猜测有可能,尽管不太可能,两个用户可能会使用相同的 insertedTime 值创建 post。那么您真正需要的是添加 ID 以确保它们是唯一的:

    PRIMARY KEY ((postYear, postMonth, postDay, postHour), insertedTime, ID)
    
  3. 在这一点上,我会考虑将您的 IDinsertedTime 列合并为 timeuuid 类型的单个 ID 列。通过这些更改,您的最终 table 看起来像:

    CREATE TABLE Posts(
      ID timeuuid,
      postYear int,
      postMonth int,
      postDay int,
      postHour int,
      title text,
      contentURL text,
      userID text,
      PRIMARY KEY ((postYear, postMonth, postDay, postHour), ID)
    ) WITH CLUSTERING ORDER BY (ID DESC);
    

    无论您使用哪种编程语言,都应该有一种方法可以从插入的时间生成 timeuuid,然后从 timeuuid 值中提取该时间(如果您想在 UI 之类的。 (或者您可以使用 CQL timeuuid functions 进行转换。)

关于您关于查询多个分区的问题,是的,这样做完全没问题,但如果您不小心,可能 运行 会遇到麻烦。例如,如果有 48 小时没有 posts 会怎样?您是否必须发出 48 次 return 空结果的查询才能最终在第 49 次查询中得到一些结果? (这可能会非常缓慢并且用户体验糟糕。)

您可以采取一些措施来尝试缓解这种情况:

  1. 减少分区的粒度。例如,不要按小时执行 post 秒,而是 前 post 秒,或 月 post 秒。如果您知道这些分区不会变得太大(即用户不会创建太多 post 分区变得很大),那可能是最简单的解决方案。
  2. 创建第二个 table 以跟踪哪些分区实际上有 post。例如,如果您坚持按小时计算 posts,则可以像这样创建 table:

    CREATE TABLE post_hours (
      postYear int,
      postMonth int,
      postDay int,
      postHour int,
      PRIMARY KEY (postYear, postMonth, postDay, postHour)
    );
    

    然后,只要用户添加新的 post,您就可以插入此 table(使用 Batch)。然后,您可以在查询 Posts table 之前查询 table first 以确定哪些分区具有 posts 并且应该是查询(从而避免查询一大堆空分区)。