您的位置:首页 > 博客中心 > 数据库 >

leveldb源码分析--SSTable之Compaction

时间:2022-03-10 17:50

对于compaction是leveldb中体量最大的一部分,也应该是最为复杂的部分,为了便于理解我们首先从一些基本的概念开始。下面是一些从doc/impl.html中翻译和整理的内容:

Level 0

当日志文件超过一定大小的阈值是 (默认为 1MB):

  • 建立一个新的memtable和日志文件,以后的操作都是用新的memtable和日志文件
  • 后台进行如下操作:
    • 将旧的 memtable写到SSTable中(过程为先转为immtable_table,然后遍历写入)
    • 废弃旧的 memtable
    • 删除旧的 memtable和日志文件
    • 将新的SSTable加到level 0中.

这是doc/impl.html中的说明,但是在源代码中我们可以看到在MakeRoomForWrite函数中有逻辑,当满足一些其他条件之后(这里的其他条件不涉及到这个阈值大小)(mem_->ApproximateMemoryUsage() > options_.write_buffer_size) 就会有

Files in directory Microseconds to open a file 1000 9 10000 10 100000 16

 

了解了compaction的一些原理和机制以后我们该回到代码来看看具体的代码流程是怎么样的,首先回到DBimpl中的MakeRoomForWrite

Status DBImpl::WriteLevel0Table(MemTable* mem, VersionEdit* edit, Version* base) { 
  meta.number = versions_->NewFileNumber();
  pending_outputs_.insert(meta.number);
  Iterator* iter = mem->NewIterator();
  //新生成一个Table_builder负责写文件
    s = BuildTable(dbname_, env_, options_, table_cache_, iter, &meta);

  // Note that if file_size is zero, the file has been deleted and 
  // should not be added to the manifest.
  int level = 0;
  if (s.ok() && meta.file_size > 0) {
    const Slice min_user_key = meta.smallest.user_key();
    const Slice max_user_key = meta.largest.user_key();
    if (base != NULL) {
      /* 找到一个当层未overlap 且上册overlap 不会过多(kMaxGrandParentOverlapBytes)的层返回*/ 
      level = base->PickLevelForMemTableOutput(min_user_key, max_user_key);
    }
    //将文件加到versionedit中
    edit->AddFile(level, meta.number, meta.file_size,
                  meta.smallest, meta.largest);
  }
  CompactionStats stats;
  stats.micros = env_->NowMicros() - start_micros;
  stats.bytes_written = meta.file_size;
  stats_[level].Add(stats);
  return s;
}

这里有一个唯一需要注意的是——将Memtable dump到磁盘以后并不是如文档描述的“将新的SSTable加到level 0中.”,而是会用一个函数PickLevelForMemTableOutput选择一个最高的可以将这个SSTable放入的level中。一般来说会是level 0,但是还是存在一些特殊情况可以将其放到更高的level中,这样可以降低Compaction的频率。PickLevelForMemTableOutput的逻辑简单,请读者自行阅读。

至此comaction流程相关的函数就分析完了,本节内容比较多,但是只要静下心来慢慢品读理解还是不难的。至此leveldb中剩下的还有recover,new (新建一个数据库)、snapshot、get相关的代码没有分析了。我们在compaction的分析过程中涉及到了很多有关version的类、方法、结构,leveldb的vesion是整个系统极其重要的一环,而且recovery,snapshot,get在一定程度上都会依赖于version的实现,所以接下来的文章准备对version相关的内容进行介绍。敬请期待……

leveldb源码分析--SSTable之Compaction,布布扣,bubuko.com

热门排行

今日推荐

热门手游