4

在 Cassandra 中设置一个表,设置如下:

  • 主键列
    • shard - 1 到 1000 之间的整数
    • last_used- 时间戳
  • 值列:
    • value - 一个 22 个字符的字符串

如果如何使用此表的示例:

shard     last_used          | value
------------------------------------
457       5/16/2012 4:56pm     NBJO3poisdjdsa4djmka8k    >--     Remove from front...
600       6/17/2013 5:58pm     dndiapas09eidjs9dkakah       | 
...(1 million more rows)                                    |
457       NOW                  NBJO3poisdjdsa4djmka8k    <--     ..and put in back

该表用作一个巨大的队列。很多线程都试图“弹出”具有最低last_used值的行,然后及时将last_used值更新为当前时刻。这意味着一旦读取了一行,因为last_used它是主键的一部分,该行将被删除,然后在“队列末尾”将具有相同shard,value和更新时间的新行添加到表中。last_used

之所以shard存在,是因为有太多进程试图pop将最旧的行从队列的前面移到后面,如果只有一个进程可以同时访问队列,它们就会严重地相互瓶颈。这些行被随机分成 1000 个不同的“碎片”。每次线程从队列的开头“弹出”一行时,它都会选择一个当前没有其他线程正在使用的分片(使用 redis)。

天哪,我们一定是哑巴!

我们遇到的问题是这个操作变得非常慢,大约 30 秒,几乎是永恒。

我们只使用 Cassandra 不到一个月,所以我们不确定我们在这里做错了什么。我们已经得到一些迹象,也许我们不应该在同一张桌子上写太多和读太多。我们不应该在 Cassandra 中这样做吗?或者我们的操作方式或我们配置它的方式是否存在一些细微差别,我们需要更改和/或调整?如何解决这个问题?

更多信息

  • 我们正在使用 MurMur3Partitioner(新的随机分区器)
  • 该集群目前在 9 台服务器上运行,每台服务器具有 2GB RAM。
  • 复制因子为 3

非常感谢!

4

3 回答 3

7

这是你不应该使用 Cassandra 的东西。您遇到性能问题的原因是因为 Cassandra 必须扫描成山的墓碑才能找到剩余的活动列。每次您删除某些内容时,Cassandra 都会写一个墓碑,这是该列已被删除的标记。在进行压缩之前,实际上不会从磁盘中删除任何内容。压缩时 Cassandra 会查看墓碑并确定哪些列已死,哪些仍处于活动状态,将死列丢弃(但随后还有 GC 恩典,这意味着为了避免列的虚假复活,Cassandra 将墓碑保留在周围一段时间)。

由于您不断地添加和删除列,因此会有大量的墓碑,它们将分布在许多 SSTable 中。这意味着 Cassandra 必须做大量的开销工作来拼凑一行。

阅读博文“Cassandra 反模式:队列和类似队列的数据集”了解更多详细信息。它还向您展示了如何跟踪查询以自己验证问题。

从您的描述中并不完全清楚什么是更好的解决方案,但它听起来很像 RabbitMQ 之类的消息队列,或者 Kafka 可能是一个更好的解决方案。它们具有恒定的流失和 FIFO 语义,而 Cassandra 则不是。

有一种方法可以使 Cassandra 的查询不那么繁重,您可以尝试一下(尽管我仍然会说 Cassandra 是这项工作的错误工具):如果您可以在查询中包含时间戳,您应该主要点击实时列. 例如,将last_used > ?(其中 ? 是时间戳)添加到查询中。这需要您对第一个时间戳有一个粗略的了解(并且不要通过查询来找到它,这将同样昂贵),因此它可能对您不起作用,但它会减轻一些负担卡桑德拉。

于 2013-06-18T06:37:36.223 回答
2

系统似乎处于压力之下(2GB 或 RAM 可能不够)。请让 nodetool tpstats 运行并报告其结果。

于 2013-06-18T01:13:12.487 回答
1

使用 RabbitMQ。对于这个应用程序来说,Cassandra 可能是一个糟糕的选择。

于 2013-06-18T04:49:02.287 回答