所谓的版本,简单地说,指的是leveldb中各个level层的文件信息。显然,随着compaction的进行和新的memtable写入生成新的sstable,版本会不断变化。版本除了记录各层的文件信息外,还记录各层关于compaction的的信息,比如在对于当前版本,最适合进行compaction的level是哪层,以及这层中最适合compaction的是哪个文件等信息。
和版本相关的类主要是以下三个:
- class Version
- class VersionSet
- class VersionEdit
其中version是单独一个版本的信息,VersionSet是版本信息的集合,里面包含多个通过链表组织的版本,VersionEdit主要是记录版本的变化信息。下面我们将逐一介绍这三个类,以及通过观察版本的变化来了解它们的作用以及如何工作。
先来看一下版本(Version)的数据成员
vset_指针是指向包含该版本的版本集合,一般每个leveldb实例中都有一个版本集合,用于管理从启动开始产生的所有版本信息。因为版本集合是通过链表的信息对版本进行管理,因此下面两个数据成员就是链表指针。refs_是一个计数器,用于生命周期管理。再继续就是对应该版本的各个层的文件信息 了,这是一个二维数组,数组中的每个子数组代表一个层,子数组中的每个元素是对应该层的一个文件的元信息。最后面三个成员主要是用于统计当前版本的compaction信息,通过这些信息可以快速判断应该对哪个level进行compaction。
VersionEdit**用于记录对版本的修改**,其中的关键数据成员是deleted_files_和new_files_。deleted_files是一个set,包含在当前版本在此次修改中被删除的文件,new_files_是一个数组,记录此次修改中新增加的文件。
因此通过从当前版本中的删去包含在deleted_files_中的文件,以及添加包含在new_files_中的文件,就可以得到一个新的版本。
leveldb通过VersionSet管理自数据库启动开始的所有版本。通过一个链表将所有版本连接起来,最新的版本位于链表尾部。这个链表是一个双向链表,它的头部用dummy_versions_数据成员标记。VersionSet_中的current_数据成员指向当前数据库的版本信息。VersionSet_中的数据成员compact_pointer_数组主要是标记每个level下次进行compaction时应该选择哪个文件。compact_pointer_里面是一个key数组,比如如果下次进行compaction的是level i,则应该选择level i中第一个key大于compact_pointer_[i]的文件,同时会更新compact_pointer_[i],保证下次compaction会从一个新的文件进行。