在C * 1.2.x集群中,我们有7个键空间,每个键空间包含一个使用宽行的列族。 cf使用LCS。我定期在行中进行删除。最初,每一行每天最多可以包含1个条目。超过3个月的条目将被删除,并且每周最多保留1条条目。我已经运行了几个月,但是并没有真正回收磁盘空间。我需要调查原因。对我来说,墓碑似乎还没有被清除。每个键空间都有大约1300个sstable文件(* -Data.db),每个文件的大小约为130 Mb(sstable_size_in_mb为128)。每个CF中的GC宽限秒为864000。未指定tombstone_threshold,因此应默认为0.2。我应该怎么看才能找出为什么不回收磁盘空间?

最佳答案

在cassandra邮件列表here上,我已经回答了类似的问题

为了进一步详细说明,至关重要的是,您应该大致理解Levelled Compaction Strategyleveldb(给定正常的写入行为)

总结以上内容:


数据存储组织为“级别”。每个级别比其下的级别大10倍。级别0的文件具有重叠范围。较高级别的文件在每个级别中没有重叠的范围。
新写入将存储为进入第0级的新sstable。每隔一段时间,level 0中的所有sstable都会“压缩”到第1级sstable,然后向上压缩到第2级sstable等。
给定键的读取将执行〜N次读取,N是树中的级别数(这是数据集总大小的函数)。级别0的sstables均被扫描(因为没有约束,每个sstable都具有与兄弟姐妹不重叠的范围)。但是,级别1和更高级别的sstables没有重叠范围,因此数据库知道级别1中的哪个1确切sstable涵盖了您要求的密钥范围,级别2等等。
LCS树在cassandra中的布局存储在一个json文件中,您可以轻松检查它-您可以在与keyspace + ColumnFamily的sstables相同的目录中找到它。这是我的一个节点的示例(结合jq工具+ awk进行总结):

$ cat users.json | jq ".generations[].members|length" | awk '{print "Level", NR-1, ":", $0, "sstables"}'
Level 0 : 1 sstables
Level 1 : 10 sstables
Level 2 : 109 sstables
Level 3 : 1065 sstables
Level 4 : 2717 sstables
Level 5 : 0 sstables
Level 6 : 0 sstables
Level 7 : 0 sstables



正如您已经注意到的,sstable的大小通常相等,因此您可以看到每个级别的大小大约是前一个级别的10倍。我希望在上面的节点中能够满足〜5 sstable读取中的大多数读取操作。一旦我添加了足够的数据以使Level 4达到10000 sstable,并且Level 5开始被填充,我的读取延迟就会稍有增加,因为每次读取都会产生1 sstable读取以满足。 (在切线上,cassandra提供了桶状直方图供您检查所有这些统计信息)。

有了以上这些,让我们逐步完成一些操作:




我们发出一个写[“ bob”] [“ age”] =30。这将输入level0。通常很快就会压缩到第1级。慢慢地,它将花时间在每个级别上,但是随着越来越多的写入进入系统,它将向上迁移到最高级别N
我们发布[[bob]] [“ age”]的读物。然后,DB可以检查从最低到最高的每个级别-一旦找到可以返回的数据。如果达到最高级别但尚未找到它,则该节点上不存在数据。如果在任何级别找到逻辑删除,它都可以返回“未找到”,因为数据已被删除





我们发出一个删除[“ bob”] [“ age”]。这将以普通写入方式输入level0,并带有特殊值“ column tombstone”。通常很快就会压缩到第1级。慢慢地,它将花费时间在每个级别上,但是随着更多的写入进入系统,它将向上迁移到最高级别N。在每次压缩期间,如果将一起压缩的sstable有一个墓碑(例如l1中)和一个实际值(例如l2中的“ 30”),逻辑删除“吞噬”该值并影响该级别的逻辑删除。但是,该逻辑删除尚不能丢弃,必须坚持下去,直到有机会压缩到每个级别为止,直到达到最高级别为止–这是确保L2的年龄= 30,L3的年龄= 29岁,而L4的年龄甚至更年长= 28岁,他们所有人都有机会被墓碑摧毁。只有当墓碑达到最高水平时,它才能真正被完全丢弃
我们发布[[bob]] [“ age”]的读物。然后,DB可以检查从最低到最高的每个级别-一旦找到可以返回的数据。如果达到最高级别但尚未找到它,则该节点上不存在数据。如果在任何级别找到逻辑删除,它都可以返回“未找到”,因为数据已被删除





我们发出一个删除[“ bob”]。这将以普通写入方式输入level0,并带有特殊值“行逻辑删除”。它将遵循与上述列级逻辑删除相同的逻辑,除非它与行“ bob”下任何列的任何现有数据冲突,它将丢弃它。
我们发布[[bob]] [“ age”]的读物。然后,DB可以检查从最低到最高的每个级别-一旦找到可以返回的数据。如果达到最高级别但尚未找到它,则该节点上不存在数据。如果在任何级别找到逻辑删除,它都可以返回“未找到”,因为数据已被删除




我希望这能回答您的问题,关于为什么cassandra中的删除(尤其是使用LCS的删除)实际上会消耗空间而不是释放空间(至少在最初是这样)。逻辑删除所附加的行和列的大小(实际上可能比您拥有简单值的情况下要删除的值大)。

这里的关键点是,在cassandra实际丢弃它们之前,它们必须遍历所有级别直到最高级别L,而这种冒泡的主要驱动力是总写入量。

关于cassandra - 在Cassandra中使用LCS时延迟了清除墓碑的原因,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27862808/

10-09 19:45