leveldb源码解析四——版本管理

leveldb支持数据的多个版本,可以获取某个版本的快照,遍历或者查找这个版本中的key

class LEVELDB_EXPORT DB {
  ...
  // Return a handle to the current DB state.  Iterators created with
  // this handle will all observe a stable snapshot of the current DB
  // state.  The caller must call ReleaseSnapshot(result) when the
  // snapshot is no longer needed.
  virtual const Snapshot* GetSnapshot() = 0;

  // Release a previously acquired snapshot.  The caller must not
  // use "snapshot" after this call.
  virtual void ReleaseSnapshot(const Snapshot* snapshot) = 0;
  ...
};

同时对某个key更新时,不会直接在原key上更新,而是提交一个版本号更大的record,原版本的key会一直保留,直到在compaction时,低版本的key被merge到高版本的key。

Version

Version保存的是当前版本中的sstable和相关compaction信息。通过引用计数管理生命周期,通过list方式组织。Version封装了在compaction时对sstable的一系列操作。

class Version {
  ...
  VersionSet* vset_;  // VersionSet to which this Version belongs
  Version* next_;     // Next version in linked list
  Version* prev_;     // Previous version in linked list
  int refs_;          // Number of live refs to this version

  // List of files per level
  std::vector<FileMetaData*> files_[config::kNumLevels];

  // Next file to compact based on seek stats.
  FileMetaData* file_to_compact_;
  int file_to_compact_level_;

  // Level that should be compacted next and its compaction score.
  // Score < 1 means compaction is not strictly needed.  These fields
  // are initialized by Finalize().
  double compaction_score_;
  int compaction_level_;
};

VersionEdit

每次compaction之后,会产生一个新的版本,新版本在sstable文件组成上面和老版本上存在差异,这个差异通过VersionEdit表示,老版本通过应用VersionEdit之后,就可以得到新版本。

struct VersionEdit {

  typedef std::set<std::pair<int, uint64_t>> DeletedFileSet;
  // 比较器名称
  std::string comparator_;
  // 日志编号,该日志之前的数据均可删除
  uint64_t log_number_;
  // 已经弃用
  uint64_t prev_log_number_;
  // 下一个文件编号(ldb、idb、MAINFEST文件共享一个序号空间)
  uint64_t next_file_number_;
  // 最后的seq_num
  SequenceNumber last_sequence_;
  // 
  bool has_comparator_;
  bool has_log_number_;
  bool has_prev_log_number_;
  bool has_next_file_number_;
  // 
  bool has_last_sequence_;
  // 记录每一层所对应需要压缩的
  std::vector<std::pair<int, InternalKey>> compact_pointers_;
  // 相比上次version而言,本次需要删除的文件有哪些
  DeletedFileSet deleted_files_;
  // 相比上次version而言,本次新增的文件有哪些
  std::vector<std::pair<int, FileMetaData>> new_files_;
};

VersionEdit中封装了对上述几个字段的序列化和反序列化。

Manifest

Manifest文件可以看作是VersionEdit的日志,为了快速恢复需要将这些变更持久化到磁盘上。Manifest和WAL使用同样的格式就VersionEdit,一个VersionEdit就是一条record。在DB重启时,通过解析当前Manifest文件,就可以恢复到最新的版本。

VersionSet

通过VersionSet来管理多个Version,整个db只有一个。
leveldb源码解析四——版本管理_第1张图片

class VersionSet {
  ...
  Env* const env_;
  const std::string dbname_;
  const Options* const options_;
  TableCache* const table_cache_;
  const InternalKeyComparator icmp_;
  uint64_t next_file_number_;
  uint64_t manifest_file_number_;
  uint64_t last_sequence_;
  uint64_t log_number_;
  uint64_t prev_log_number_;  // 0 or backing store for memtable being compacted

  // Opened lazily
  WritableFile* descriptor_file_;
  log::Writer* descriptor_log_;
  Version dummy_versions_;  // Head of circular doubly-linked list of versions.
  Version* current_;        // == dummy_versions_.prev_

  // Per-level key at which the next compaction at that level should start.
  // Either an empty string, or a valid InternalKey.
  std::string compact_pointer_[config::kNumLevels];
  ...
};

你可能感兴趣的:(leveldb,c++,开发语言,缓存,database)