RocksDB: Version & VersionSet


这一部分和 LevelDB 几乎完全一致,可以按照 LevelDB 来理解。

由于 SST 是生成后就不可变的,所以 LSM-Tree 的合并就是生成 Compact 后的新 SST 并删除旧的 SST,{17,40} {12,19} {22,45} => {12,45} 这个样子。可问题来了,因为 RocksDB 支持多客户端线程,所以如果在执行 Compact 时,{17 40} {12 19} {22 45} 正在被某个客户端读时,怎么办?

很显然,此时不能删除。RocksDB 在删除 SST 时,需要等到它/它们的引用 ref == 0 时才可以删除,即其上没有任何读操作了。

所以实际上,刚刚 Compact 完的结构是这样的:{17,40} {12,19} {22,45} => {17 ,40} {12,19} {22,45} {12,45},也就是新旧暂时都存在 LSM-Tree 中。

新旧SST共存

这样就又有问题了。此时如果有新的范围在 12~45 间的读取,到底是去旧的 SST 读还是去新的 SST 读,当然是要去新的 SST 中读。那么就需要一个办法,来区分出旧的 SST 和新的 SST,Version 就是干这个的。

  • 旧有的 SST 组成一个 Version。
  • Compact 操作称为 VersionEdit,一个 VersionEdit 就是一次 Compact。VerionEdit 记录了哪些 SST 要被删除,哪些 SST 被新建。Version + VersionEdit => NewVersion。
  • Compact 后不着急删除旧有的 Version,而是让生成一个新的 Version,包括新的 SST 和未被 Compact 的 SST,新旧 Version 是共存的。
  • 假设 Version1 在生成 Version2 的时候,Version1 正在服务很多读请求,那 Version1 自然不能丢。
    • 当 Version2 生成好了之后,Version2 也开始服务很多读请求。
    • Version2 到达某一时刻,也会开始进行 Compact,生成Version3。此时若 Version2 也在服务读请求,那自然也不能丢。
    • 整体形成 {Version1、Version2、Version3} 的局面。

当前 DB 的所有 Version 集合,就是 VersionSet。

VersionSet

因为新来的读请求都是交给最新的 Version 去读的,所以旧的 Version 终会有一刻不再被读,此时该 Version 就会被清理掉,其中老旧的 SST 即会被删除。

万一旧的 Version 正在被写,怎么办呢?开玩笑,SST 一旦生成,只能读和删,是不可能再去写入的。


文章作者: SrcMiLe
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 SrcMiLe !
评论
  目录