leveldb源码剖析----compaction

根据前面的分析,背景线程的主体工作在BackgroundCompaction函数中完成。这个函数主要完成以下两个工作:

  1. 如果imm_非空,则将imm_写入到磁盘中生成新的sstable文件
  2. 对level中的文件进行合并。合并的目的主要是避免某个level中sstable文件过多,并且可以通过合并的过程删除掉过期的key-value和被用户删除的key-value。

这篇文章主要是从BackgroundCompaction函数开始,分析level中文件合并的过程


void DBImpl::BackgroundCompaction() { //在背景线程中执行
 mutex_.AssertHeld();

  if (imm_ != NULL) {
    CompactMemTable(); //将imm_写到level 0
    return;
  }

这部分主要是完成上面所说的第一个工作,将imm_写入level 0 中。因为这个函数需要处理很多整个数据库共享的数据结构,比如imm_,versions_等,因此必须保证在临界区中执行。

  Compaction* c;
  bool is_manual = (manual_compaction_ != NULL);
  InternalKey manual_end;
  if (is_manual) {
    ManualCompaction* m = manual_compaction_;
    c = versions_->CompactRange(m->level, m->begin, m->end); 
    m->done = (c == NULL);
    if (c != NULL) {
      manual_end = c->input(0, c->num_input_files(0) - 1)->largest;
    }
    Log(options_.info_log,
        "Manual compaction at level-%d from %s .. %s; will stop at %s\n",
        m->level,
        (m->begin ? m->begin->DebugString().c_str() : "(begin)"),
        (m->end ? m->end->DebugString().c_str() : "(end)"),
        (m->done ? "(end)" : manual_end.DebugString().c_str()));
  }

这部分是在设置manual_compaction_ 的时候被执行,它主要是用于测试数据库的compaction功能,用于debug,数据库实际运行时一般不会运行这段代码,这里且略过,不过从功能实现上和后面的分析也是一样的。

else {
    c = versions_->PickCompaction(); //找出最适合compaction的level
  }

这个条件分支是一个重点,它负责从数据库中选出适合进行compaction的level。它将返回可以进行compaction的level中的文件元信息,这些元信息存储在Compaction类中

可以看一下compaction的数据成员:


这里写图片描述

这个compaction将会合并level和level+1中的部分文件。

如果我们深入到PickCompaction就会看到leveldb是怎么选择需要进行compaction的level的。

leveldb首先从当前的versions中选择一个最适合进行compaction的level,这里的最适合主要是通过版本控制里面的compaction_score_变量进行衡量,同时每个版本都会有一个变量跟踪当前版本中最适合进行compaction的level(current_->compaction_level_)。除此之外,leveldb为每个level中的文件维持一个 数组compact_pointer_,这个compact_pointer_[level]指向当前level中上次被compaction的最大key的值,因此下次对这个level进行compaction时,就要从key大于compact_pointer_[level]的文件开始,而且我们可以看到,通常是选择第一个largest key大于compact_pointer_[level]的文件作为当前level需要进行compaction的文件。

从当前的level选择出适合进行compaction的文件后,我们就可以通过版本控制中的元信息找到这个文件所包含的key的最大值和最小值,通过这个最大值和最小值,我们就可以找到level+1中有哪些文件和level中的这个文件的key可能有重合,然后将这些文件和level中的那个文件进行compaction,compaction后的文件放入到level+1中。需要注意的是,每次compaction可能生成多个文件,而不是一个compaction只生成一个文件

回到上面的compac

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值