在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这样做吗?或者,我们正在采取的方式或我们配置的方式可能需要改变和/或调整?怎么可能麻烦这个?
非常感谢!
这是你不应该使用Cassandra的东西.你遇到性能问题的原因是因为Cassandra必须扫描一下墓碑山才能找到剩余的实时列.每当你删除Cassandra写一个墓碑的东西时,它就是一个标记,该列已被删除.在压缩之前,实际上没有从磁盘中删除任何内容.当压缩Cassandra看着墓碑并确定哪些列已经死亡以及哪些列仍然存在时,死亡的那些被丢弃(但是之后还有GC恩典,这意味着为了避免列的虚假复活,Cassandra会保留墓碑周围的墓碑一段时间更长).
由于您不断添加和删除列,因此会有大量的墓碑,并且它们将分布在许多SSTable上.这意味着Cassandra必须做很多工作才能将一行拼凑起来.
阅读博客文章"Cassandra反模式:队列和类似队列的数据集"以获取更多详细信息.它还向您展示了如何跟踪查询以自行验证问题.
从你的描述中不完全清楚什么是更好的解决方案,但它听起来像RabbitMQ这样的消息队列,或者可能是Kafka更好的解决方案.它们具有恒定的流失和FIFO语义,而Cassandra则不然.
有一种方法可以让Cassandra的查询不那么重,你可以试试(虽然我仍然会说Cassandra是这个工作的错误工具):如果你可以在查询中包含一个时间戳,你应该点击大多数实时列.例如last_used > ?,在查询中添加(其中?是时间戳).这要求您大致了解第一个时间戳(并且不进行查询以找出它,这将是同样昂贵的),因此它可能对您不起作用,但它会占用一些负载卡桑德拉
| 归档时间: |
|
| 查看次数: |
908 次 |
| 最近记录: |