1

我是第一次玩 Cassandra,我觉得我了解了基础知识和限制。例如,我正在使用以下模型来存储由标签收集的推文。

create table posts
(
    id text,
    status text,
    service text,
    hashtag text,
    username text,
    caption text,
    image text,
    link text,
    repost boolean,
    created timestamp,
    primary key (hashtag, created)
);

这对于我需要的查询类型非常有效:

select * from posts where hashtag = 'demo' order by created desc;

但是,如果我理解正确,我可以使用单数“演示”分区键存储的帖子数量有一个上限,更重要的是,必须存储与“演示”分区键匹配的整个帖子集每个副本。如果我理解正确,我可能应该使用更随机或可变的分区键(可能是id帖子的),但我不知道使用什么不会改变查询的要求。

如果我id用作分区键(例如PRIMARY KEY (id, created))并在主题标签列上添加二级索引,则在运行查询时会出现以下错误:

ORDER BY with 2ndary indexes is not supported.

我知道要使用 ORDER BY,分区键必须在 where 子句中出现,因此我最初的想法是使用主题标签。

我是不是想太多了,还是分区键有更好的候选者?

4

1 回答 1

2

您前进的方向取决于您期望的写入量以及您的集群有多大。

如果您有一个小型用户社区和一个小型集群,那么您可能会想太多。一个分区理论上最多可以容纳 20 亿行。这是一个很大的数字,有人真的想查看几千条最近的推文以获得标签吗?因此,您可能会有某种清理机制,例如在一段时间后使用 TTL 删除推文,这将释放分区中的空间,使您远低于 20 亿行的限制。

如果您不想清理旧推文,但想将它们保存多年,那么您可能需要使用这样的复合分区键:

primary key ((hashtag, year), created)

这将按标签和年份划分推文,因此每个标签每年可以存储多达 20 亿条推文。

按标签分区的好处是,Cassandra 可以保留按创建时间戳排序的标签的推文,如您所示,使用单个查询轻松检索最新的推文。

但是,如果您的用户社区很大,那么更值得关注的问题是避免热点。如果您只使用主题标签和像年份这样的时间箱作为分区键,那么所有读取和写入都将针对该主题标签的少量副本。如果某个主题标签在某一天非常活跃,那么根据您使用的复制因子,您的所有读取和写入都将只发送到一个或两个节点。

如果你想分散读写负载,你需要增加标签的基数,以便它映射到多个节点。使用 id 作为分区键可以实现这一点,但是这样做太过分了,因为那时每条推文都将位于一个单独的分区中,并且您将没有排序或简单的方法来检索主题标签的最新推文。

因此,更好的方法是创建单独的箱或桶,如下所示:

primary key ((hashtag, bin), created)

您创建的 bin 数量取决于您的写入负载。假设您决定 10 个节点可以处理热门主题标签的写入负载,那么 bin 将是 0 到 9 之间的值。

有多种方法可以设置 bin 编号。您可以将 id 以 10 为模,或者选择 0 到 9 之间的随机数,或者从某些字段组合生成哈希值,然后取模 10 的结果。无论您选择哪种方法,请确保从 0 到 9 的数字具有相同的可能性,以便您的数据在 bin 分区中均匀分布。

使用多个垃圾箱,检索 x 条最新推文的主题标签并不容易,因为您需要查询所有垃圾箱并合并结果。您可以并行地对主题标签的每个 bin 发出查询,然后在客户端合并结果。或者您可以使用 IN 子句执行单个查询,如下所示:

select * from posts where hashtag = 'demo' and bin IN (0,1,2,3,4,5,6,7,8,9) AND created > ...

但是 Cassandra 不会对单个查询的结果进行排序,因此您必须在客户端进行排序,这比合并单独的有序查询要慢。

现在在许多情况下,主题标签的体积很小,因此您可能不想为它们使用十个垃圾箱,除非它们变热。如果是这样,您可以在您的应用程序中使其动态化,通常只使用 bin 0,但是当发现标签很受欢迎时,增加 bin 的数量。您可以使用 bin 0 中的静态列来跟踪主题标签的活动 bin 数量。

您应该避免使用二级索引。它们在 Cassandra 中的效率非常低。

于 2015-12-26T20:33:26.457 回答