Cassandra时间序列建模

时间:2017-02-06 16:29:52

标签: database cassandra time-series scalability data-modeling

我正在尝试设计一个基于Cassandra的时间序列服务,它将跟踪一些日志信息。 数据库将显示相对较高的写入量(预计每天约500万次插入)和较少频率但大量读取(假设一天的数据或一个月的数据)。

一个日志条目的简化数据模型看起来像这样(实际上它有50个左右的列):

log_datetime date
log_some_field text
log_some_other_field text

大多数读取查询都围绕从特定日期范围选择数据,始终按日期降序排序。 (例如SELECT * FROM logs WHERE log_datetime >= 2012-01-01 and log_datetime <= 2012-02-01 ORDER BY log_datetime DESC)。这通常需要相当长的时间,所以我想尽可能地优化它。

由于按日期排序和过滤是最重要的功能,只要写入不是太糟糕,第一个想法是定义类似这样的东西(其中log_day是一年中的某一天):

CREATE TABLE logs(
  log_day tinyint
  log_datetime timeuuid
  log_some_field text
  log_some_other_field text
  PRIMARY KEY (log_day, log_datetime)
  WITH CLUSTERING ORDER BY (log_datetime DESC)
)

我的理解是,这将使检索在订购数据时获得良好的效果,并且需要一个分区来检索一天(我可以在客户端处理选择了几天的情况)。 但是,这会使写入到单个服务器,这将显着影响写入性能。另一个选择是选择一些随机集作为分区键,并以循环方式从客户端分配到每个,这将使写入更快和可扩展,但会导致更差的读取性能,尤其是如果我们必须重新排序数据。我见过的大多数示例通常在数据集中都有自然分区键,比如user_id或post_id,这不是我的情况。

这里有人有类似的用例吗?如果是这样,你为获得不错的表现做了哪些权衡?您知道在这些用例中表现更好的任何数据库吗?

1 个答案:

答案 0 :(得分:1)

正如您所注意到的,使用day作为分区键意味着写入一整个主节点一整天。数据基于复制因子在Cassandra中复制,通常为3.因此,在任何给定的日期都会写入三个节点。

如果数据量很低,这可能是可以接受的。通常它不是,并且会使用某种时间桶,例如在应用程序中计算的5或10分钟间隔。

CREATE TABLE logs(
  log_day tinyint
  timebucket tinyint
  log_datetime timeuuid
  log_some_field text
  log_some_other_field text
  PRIMARY KEY ((log_day, timebucket) log_datetime)
  WITH CLUSTERING ORDER BY (log_datetime DESC)
)

为存储桶选择合适的时间间隔与预期的数据量有关。每天写入500M,即每秒约6K。你的时间桶可以在一小时内完成,因此你只有6个(使用10分钟),或者整天都有144个独特的桶。在读取结果时,您的应用程序必须读取给定日期的所有存储桶并合并(但不能排序)结果。

在syslog类型的应用程序中,在分区键中使用severity plus day可以帮助使用自然键在集群中分配负载。它仍然是块状的,因为信息msgs的数量远远大于警告,错误或致命消息。