我想将来自多个来源的数据存储在 Cassandra 中,并每小时运行一次作业以仅处理特定时间的数据点。为此使用的最佳架构是什么?
为了避免出现热点,我不能将一个小时的所有数据都放在一个分区中,因此每个小时的数据需要分布在多个分区中。
所以我看到了两种允许按小时查询的方法:
为每个小时创建一个新表,并在没有 where 子句的情况下对表执行 select * 以读取该小时。我认为这对于读取和写入来说会很高效,但是必须管理这么多表会很烦人。
每周创建一个新表,并为一周内的小时数(即 1 到 168)创建一个列,并在其上创建二级索引。然后我可以选择 * where hour=x。这似乎可行,但我担心如果有很多行,它就无法很好地扩展。
有谁知道哪种方法的扩展性更好?有更好的方法吗?
谢谢。
最佳答案
在这种情况下,您可以使用“桶”。桶是一种将分区分成几个独立部分的方法。例如,假设您的架构如下所示:
CREATE KEYSPACE timeseries WITH replication = {
'类':'SimpleStrategy','replication_factor':1
};
使用时间序列;
每小时创建一个表(
source_id 文本,
小时文本,
日期时间戳,
数据文本,
桶诠释,
主键((小时,桶),日期)
);
然后您可以使用 bucket
使用某个已知标识符(例如 source_id
)的哈希函数将小时分成例如 10 个分区。
在查询时,您需要指定小时
,通常还需要指定所有时段:
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 的模数,您必须检查数字是否结束在一个统一的模式。另一方面,如果您对时间戳取模,您将在一段时间内有效地将所有内容写入一个存储桶,如果存储桶的数量较少,这可能会产生热点。
关于用于每小时查询的 Cassandra 模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31453824/