LevelDB 完全解析(四):Manifest
source link: https://mp.weixin.qq.com/s/LX_l5SQq7Bb7Cxv__67t3w
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
前文回顾
文中“蓝色字体”部分均有跳转,大部分是引用了 Github 上的源码链接,可以点击【阅读原文】查看。
内容上,Manifest 文件保存了整个 LevelDB 实例的元数据,比如:每一层有哪些 SSTable。
格式上,Manifest 文件其实就是一个 log 文件 [1] 。
VersionEdit
LevelDB 用 VersionEdit 来表示一次元数据的变更。Manifest 文件保存 VersionEdit 序列化后的数据。LevelDB 的元数据变更包括:
std::string comparator_; uint64_t log_number_; uint64_t prev_log_number_; uint64_t next_file_number_; SequenceNumber last_sequence_; std::vector<std::pair<int, InternalKey> > compact_pointers_; DeletedFileSet deleted_files_; std::vector<std::pair<int, FileMetaData> > new_files_;
-
comparator_:比较器的名称,这个在创建 LevelDB 的时候就确定了,以后都不能修改。
-
log_number_:最小的有效 log number。小于 log_numbers_ 的 log 文件都可以删除。
-
prev_log_number_:已经废弃,代码保留是为了兼容旧版本的 LevelDB。
-
next_file_number_:下一个文件的编号 。
-
last_sequence_:SSTable 中的最大的 sequence number。
-
compact_pointers_:记录每一层要进行下一次 compaction 的起始 key。
-
deleted_files_:可以删除的 SSTable(level-no -> file-no)。
-
new_files_:新增的 SSTable。
VersionEdit 通过成员函数 EncodeTo [2] 和 DecodeFrom [3] 进行序列化和反序列化。一个全部字段都填上的 VersionEdit 序列化后的内容格式如下(注意,并不是每个 VersionEdit 都会由下面所有字段的内容,一般只有一部分):
kComparator comparator_ kLogNumber log_number_ kPrevLogNumber prev_log_number_ kNextFileNumber next_file_number_ kLastSequence last_sequence_ kCompactPointer level internal_key kCompactPointer level internal_key ... kDeletedFile level fileno kDeletedFile level fileno ... kNewFile level fileno file-size smallest largest kNewFile level fileno file-size smallest largest ...
Version
VersionApplyVersion [4] 是 VersionEdit 进行 apply [5] 之后得到的数据库状态——当前版本 包含哪些 SSTable [6] ,并通过 引用计数 [7] 保证多线程并发访问的安全性。读操作要读取 SSTable 之前需要调用 Version::Ref [8] 增加引用计数,不使用时需要调用 Version::UnRef [9] 减少引用计数。
VersionSet
VersionSet [10] 是一个 Version 的集合。
随着数据库状态的变化,LevelDB 内部会不停地生成 VersionEdit——进而产生新的 Version。此时,旧的 Version 可能还在被正在执行的请求使用。所以,同一时刻可能存在多个 Version。
VersionSet 用一个 链表 [11] 将这些 Version 维护起来,每生成一个 Version 就往这个链表尾部插入一个节点( AppendVersion [12] )。
更多的细节会留在读操作与 Compaction 的时候介绍。
参考资料
log 文件: https://mp.weixin.qq.com/s/Ry7FRClFz8XRut_fSYlX2g
EncodeTo: https://github.com/google/leveldb/blob/1.22/db/version_edit.cc#L41
DecodeFrom: https://github.com/google/leveldb/blob/1.22/db/version_edit.cc#L107
Version: https://github.com/google/leveldb/blob/1.22/db/version_set.h#L60
apply: https://github.com/google/leveldb/blob/1.22/db/version_set.cc#L801
包含哪些 SSTable: https://github.com/google/leveldb/blob/1.22/db/version_set.h#L154
引用计数: https://github.com/google/leveldb/blob/1.22/db/version_set.h#L151
Version::Ref: https://github.com/google/leveldb/blob/1.22/db/version_set.cc#L474
Version::UnRef: https://github.com/google/leveldb/blob/1.22/db/version_set.cc#L476
VersionSet: https://github.com/google/leveldb/blob/1.22/db/version_set.h#L167
链表: https://github.com/google/leveldb/blob/1.22/db/version_set.h#L310
AppendVersion: https://github.com/google/leveldb/blob/1.22/db/version_set.cc#L784
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK