背景
最近ceph的某个osd磁盘空间已经使用的97%了,只能先关闭osd,然后使用
bash
ceph-kvstore-tool bluestore-kv \
/var/lib/ceph/osd/ceph-x compact \
--debug_rocksdb=4
来执行compact。但是因为磁盘空间已经快慢了,发起离线compact后总会因为临时磁盘空间不够导致失败。具体的日志在与ceph-osd.x.log同目录的rados.log里面。
问题的根因
我们知道假定某次L3选择了2个文件L4选择了6个文件,那么在L6有可能新产生了6个文件。在原来的7个文件没有被清理之前,新老文件是并存的。这就导致磁盘需要额外申请6个sst的空间。当磁盘本身容量已经快满的时候,这样就很危险。
那么怎么解决呢?每次少compact一点不就行了?
解决思路
在手动compact的时候,源层有100个文件,总体积5个G。怎么办?一次把5个G的文件都进行compact?
不是的。
在手动compact过程中,有个参数max_compaction_bytes,它的默认值是25倍的单sst体积,也就是25MB*64,大概就是1.5GB。
单次手动compact 选择源层文件的的时候,当选择的源层文件提交超过max_compaction_bytes就停止选择。这样就能避免超大型的compact(这部分逻辑在CompactionPicker::CompactRange)。
我们知道了上面的原理,那我吧调用方法改成
bash
ceph-kvstore-tool bluestore-kv \
/var/lib/ceph/osd/ceph-x compact \
--debug_rocksdb=4 \
--bluestore_rocksdb_options=max_compaction_bytes=31457280
我限制成30MB,我的想法就是 每次在源层就找1个文件。这样每次都是小而美的compact。97%的磁盘空间也就够用了。
之后的问题
上面的命令确实可以执行,每次compact都能很快完成,也确实能清理一点空间,但是我发现新产生的文件体积都很小。
这就要说max_compaction_bytes的另一个作用了。
当compact新生成文件的时候,什么时候该关闭当前文件,什么时候该启用新的文件呢?具体来说有下面几个判断条件。
- 1 当sst的容量超过了那那个限定值(默认64MB)。
- 2 如果当目标层的那个sst一旦加入了某个key之后,我们发现这个新的sst和更下一层的既有sst的交叠范围(这个交叠指的是完整覆盖,也就是说这个新的key大于某个sst的最大值)大于25倍的target_file_size_base,那就该停止了,后面就要产生一个新的sst了(这部分逻辑在SubcompactionState::ShouldStopBefore)。
- 3 如果设定了sst_partitioner_factory,那么如果下一个key的前n个字节和当前的key不一致,也会切分
- 4 一次compact的最后一部分数据,有可能会不到64MB,注意sub_compact_count,只限制L0到L1。
上面逻辑里25倍的target_file_size_base,就是max_compaction_bytes。
现在这里把max_compaction_bytes调整了,compact的时候新生成sst的判断条件也就改变了。
后续思路
那咋办?max_compaction_bytes默认1.5GB,手动compact涉及的文件量太多,max_compaction_bytes太小,新生成的文件 体积又太小。
第一个思路改代码。修改CompactionPicker::CompactRange,把limit的限制改成别的值。
第二个,先用30MB清理一点空间
bash
ceph-kvstore-tool bluestore-kv \
/var/lib/ceph/osd/ceph-x compact \
--debug_rocksdb=4 \
--bluestore_rocksdb_options=max_compaction_bytes=31457280
执行一段时间后,杀掉进程,再用300MB清理一部分空间。
bash
ceph-kvstore-tool bluestore-kv \
/var/lib/ceph/osd/ceph-x compact \
--debug_rocksdb=4 \
--bluestore_rocksdb_options=max_compaction_bytes=314572800
随后就去掉这个max_compaction_bytes的限制。