表与重写和Cassandra中的一些读取。主键搜索需要30秒。 (队列)

时间:2013-06-18 00:53:54

标签: cassandra bigdata

在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是主键的一部分,该行将被删除,然后是具有相同shardvalue和更新{{{ 1}}时间被添加到表中,位于“队列末尾”。

last_used就在那里,因为有很多进程正在尝试shard队列前面最老的一行并把它放在后面,如果只有一个就可以相互严重瓶颈同时访问队列。这些行随机分成1000个不同的“碎片”。每次线程从队列的开头“弹出”一行时,它会选择一个其他线程当前没有使用的分片(使用redis)。

神圣的废话,我们一定是笨蛋!

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

我们只使用Cassandra不到一个月,所以我们不确定我们在这里做错了什么。我们已经得到一些迹象表明,也许我们不应该在同一张桌子上写这么多东西。难道我们不应该在Cassandra这样做吗?或者,我们正在采取的方式或我们配置的方式可能需要改变和/或调整?怎么可能麻烦这个?

更多信息

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

非常感谢!

3 个答案:

答案 0 :(得分:7)

这是你不应该使用Cassandra的东西。你遇到性能问题的原因是因为Cassandra必须扫描一下墓碑山才能找到剩余的实时列。每当你删除Cassandra写一个墓碑的东西时,它就是一个标记,该列已被删除。在压缩之前,实际上没有从磁盘中删除任何内容。当压缩Cassandra看着墓碑并确定哪些列已经死亡以及哪些列仍然存在时,死亡的那些被丢弃(但是那时还有GC恩典,这意味着为了避免列的虚假复活,Cassandra会保留墓碑周围的墓碑有一段时间了。)

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

阅读blog post "Cassandra anti-patterns: queues and queue-like datasets"了解更多详情。它还向您展示了如何跟踪查询以自行验证问题。

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

有一种方法可以让Cassandra的查询不那么重,你可以尝试(虽然我仍然会说Cassandra是这个工作的错误工具):如果你可以在查询中包含一个时间戳你应该打主要是活柱。例如。将last_used > ?(其中?是时间戳)添加到查询中。这要求您大致了解第一个时间戳(并且不进行查询以找出它,这将是同样昂贵的),因此它可能对您不起作用,但它会占用一些负载卡桑德拉。

答案 1 :(得分:2)

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

答案 2 :(得分:1)

使用RabbitMQ。 Cassandra可能是这个应用程序的不错选择。