用于每小时查询的Cassandra架构

时间:2015-07-16 12:12:37

标签: cassandra

我想从许多来源在Cassandra中存储数据,并且每小时运行一次作业来处理特定小时的数据点。用于此的最佳模式是什么?

为避免出现热点,我无法将所有数据放在一个分区中一小时,因此每小时的数据需要分布在多个分区中。

所以我看到两种方法允许按小时查询:

  1. 为每小时创建一个新表,并执行没有where子句的表的select *来读取该小时。我认为这对读写很有效,但是要管理这么多表会很烦人。

  2. 每周创建一个新表,并在一周内有一个小时数列(即1到168),并在其上创建一个二级索引。然后我可以做一个select * where hour = x。这似乎有效,但我担心如果有很多行,它不会很好地扩展。

  3. 有谁知道哪种方法会更好地扩展?有更好的方法吗?

    感谢。

2 个答案:

答案 0 :(得分:3)

在这样的情况下,您可以使用"水桶"。桶是将分区分成几个单独部分的方法。例如,假设您的架构如下: CREATE KEYSPACE timeseries WITH replication = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 }; USE timeseries; CREATE TABLE hourly ( source_id text, hour text, date timestamp, data text, bucket int, PRIMARY KEY ((hour, bucket), date) );

然后你可以使用bucket使用某个已知标识符的哈希函数(例如source_id)将小时分成例如10个分区。

在查询时,您需要指定hour并且通常指定所有存储桶:

SELECT * FROM hourly WHERE hour = '2015-07-20 23:00' AND bucket IN (0,1,2,3,4,5,6,7,8,9);

哈希函数非常重要,因为您希望它在不同分区之间均匀分布数据,即使已识别的哈希值不是均匀分布的,但您也不希望它是一个非常复杂的函数。

这个JSFiddle为您提供了一个示例散列函数,它非常简单,统一分发数据,并且可以使用任何语言轻松复制:http://jsfiddle.net/joscas/yfp72fq5/

否则代替散列函数,你的id的模数甚至是纪元时间的模数都可以满足而不是散列函数,但是如果你使用id的模数,你必须检查这些数字是否为'以均匀的方式结束。另一方面,如果你采用时间戳的模数,你将有效地将所有内容写入一个桶中,如果桶的数量很小,这可能会产生热点。

答案 1 :(得分:1)

您没有多少选择,正如您已经发现的那样,解决方案存在缺陷。

由于与二级索引相关的可伸缩性问题,我肯定会避免使用解决方案2。如果您现在需要解决方案,我会使用很多表。如果您可以等待,我可以使用Cassandra 3和materialized views选择合适的密钥。

HTH, 卡罗