LevelDB源码9:Version

技术 · 2022-07-09

当前版本的引用计数至少是1。生成新版本时,将旧的当前版本Unref,就是引用计数减1。

MANIFEST

简而言之:每次启动都会根据当前 current文件指向MANIFEST文件进行恢复,MANIFEST第一条记录了一个版本的全部信息,后面是迭代的变化记录。根据当前MANIFEST生成一个版本后(当前版本+改变=最新版本),就会新建一个MANIFEST,存放新建的版本,后续将其他的变化记录在这个文件中。如果数据库本身没有重启,这个manifest会一直增长,即每次重启新建MANIFEST。

manifest文件专用于记录版本信息。leveldb采用了增量式的存储方式,记录每一个版本相较于上一个版本的变化情况。

VersionEdit的内容将持久化到MANIFEST里的。即:MANIFEST里面保存的是VersionEdit。

一个Manifest内部包含若干条Session Record,其中第一条Session Record记载了当时leveldb的全量版本信息,其余若干条Session Record仅记录每次更迭的变化情况。因此,每个manifest文件的第一条Session Record都是一个记录点,记载了全量的版本信息,可以作为一个初始的状态进行版本恢复。

注意,随着leveldb运行时间的增长,一个manifest中包含的session record会越来越多,故leveldb在每次启动时都会重新创建一个manifest文件,并将第一条session record中记录当前version的快照状态。其他过期的manifest文件会在下次启动的recover流程中进行删除。leveldb通过这种方式,来控制manifest文件的大小,但是数据库本身没有重启,manifest还是会一直增长。

对于当前数据有哪些SSTable,这些SSTable属于哪一层,每一个SSTable的键范围和文件大小等信息,需要持久化到磁盘上,下一次打开数据库的时候,就可以从磁盘上读取到这些元数据,恢复内存里的数据结构,这个持久化数据就存储在MANIFEST文件中。

随着Compaction的进行, 元数据会改变,所以每次还需要将改变的元数据写到MANIFEST中。恢复元数据时,使用初始的元数据和各个改变恢复出最终的元数据。但是如果改变太多,MANIFEST太大,恢复就会太耗时,这时可以将当前的元数据写入到有一个新的MANIFEST中,而舍弃旧的MANIFEST。而CURRENT文件则存储了当前使用的MANIFEST文件是哪一个,写完MANIFEST后, 需要将CURRENT指向新的MANIFEST。

一个Manifest文件中,包含了多条Session Record。一个Session Record记录了从上一个版本至该版本的变化情况:

  • 新增了哪些sstable文件
  • 删除了哪些sstable文件(由于compaction导致)
  • 最新的journal日志文件标号等

借助这个Manifest文件,leveldb启动时,可以根据一个初始的版本状态,不断地应用这些版本改动,使得系统的版本信息恢复到最近一次使用的状态。

一个Session Record包含以下字段:

  • Comparer的名称
  • 最新的journal文件编号
  • 下一个可以使用的文件编号
  • 数据库已经持久化数据项中最大的sequence number
  • 新增的文件信息
  • 删除的文件信息
  • compaction记录信息
LevelDB
Theme Jasmine