rocksdb checkpoint 空间放大的极致优化

如果想把一个运行中的rocksdb从快设备拷贝到慢设备上,一般需要比较长的时间,在rocksdb的CreateCheckpointImpl里,这里有个非常大的锁,即db_->DisableFileDeletions();,在我们的场景里,这是几乎无法接受的,带来了非常大的空间放大。如果我们单纯是给一个version ref一下再拷贝,那么也是很大粒度的锁,这里介绍一种sst粒度的locker方案,完全绕开了rocksdb,并在线上长期(>4年)稳定运行。
步骤一,按通常的checkpoint步骤,获取db->mutex_,把memtable flush下去,并拿到最新version的所有live file,把MANIFEST拷贝出来,MANIFEST不大,拷贝很快
步骤二,重新open一下所有sst,即文件引用技术+1,并解锁db->mutex_,由于rocksdb在posix系统上删除文件都是调用unlink,所以接下来所有compaction里,rocksdb自己以为删除掉了那些旧sst,而实际那些旧sst还在
步骤三,组织一个queue,把那些sst加入到queue里,重写env层的DeleteFile,当rocksdb调用DeleteFile时,判断这个file是否是我们open过的sst,如果是,那么意味着rocksdb想在正常流程中删除这个sst,而此时这个sst被我们hold住了,此时把这个sst在queue里的优先级提高,让这个sst被优先拷贝出去
步骤四,所有sst拷贝完成,落一个类似write.done的文件