在看本篇博客之前,请先明白 Version 的概念:RocksDB: Version&VersionSet
上篇博客讲到,Compaction 之后的旧 SST 并不会被立刻删除,因为可能仍有旧 Version 在使用它,以处理正在执行的读请求。RocksDB 对其的处理几乎和 LevelDB 一致,都是当旧 SST 不再被引用时才将其删除。
首先要明白,所谓的 LSM-Tree 只是内存中的结构,而 SST 排列在磁盘上和普通文件并无二异,LSM-Tree 只是最新的 Version 去记录每个 Level 有哪些 SST 文件编号 而已。具体的实习可以参考 LevelDB:层级实现
本篇具体来讲,SST 什么时候会被删除。
RocksDB 的 Wiki 很好地解释了这个问题:Delete Stale Files,本篇只是对 Wiki 的总结。
旧有的 SST 之所以不被删除,是因为仍然有旧的 Version 在使用它,当没有任何 Version 使用它时,SST 就会被删除。每一个 SST 都有一个引用计数,当 Version 使用它时,引用加一,当该 Version 消失后,引用减一。当 SST 的引用计数归零时,就会被删除。Version 也会维持一个引用计数,这个引用指该 Version 为 Current Version 时其上的操作数,当引用计数归零后,说明没有遗留的操作了,Version 就会被删除,同时 SST 的引用计数减一。可以维持 Version 引用计数的操作有如下三个:
- Live iterators. Iterators pin the version of LSM-tree while they are created. All SST files from this version are prevented from being deleted. This is because an iterator reads data from a virtual snapshot, all SST files at the moment the iterator are preserved for data from the virtual snapshot to be available.
- Ongoing compaction. Even if other compactions aren’t compacting those SST files, the whole version of the LSM-tree is pinned.
- Short window during Get(). In the short time a Get() is executed, the LSM-tree version is pinned to make sure it can read all the immutable SST files. When no operation pins an old LSM-tree version containing an SST file anymore, the file is qualified to be deleted.
到此就可以理清 SST 删除的逻辑了,具体的细节去看 Wiki 就可。