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

Chr*_*row 4 bigdata cassandra

在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
Run Code Online (Sandbox Code Playgroud)

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

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

神圣的废话,我们一定是哑巴!

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

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

更多信息

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

非常感谢!

The*_*heo 7

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

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

阅读博客文章"Cassandra反模式:队列和类似队列的数据集"以获取更多详细信息.它还向您展示了如何跟踪查询以自行验证问题.

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

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