【leveldb】Compact(二 十 一):Minor Compaction

在这里插入图片描述

本来想写关于Version源码注解的,想想如果只是简单的Stick下源码也没什么意思,看后面放到Github上再来放链接,这样看可能好些。接下来准备分两篇来介绍下Compact流程。


本篇主要是介绍Compact流程和Minor Compaction流程详解。

Compact触发流程

图有点大,看不清的可点击放大查看。
在这里插入图片描述

接下来着重讲解下minor Compaction。


Minor Compaction
简介

Minjor Compaction就是将内存中的Memtable持久化到磁盘变成SSTable过程。
DBImpl中定义了两个MemTable:

 MemTable* mem_;
 MemTable* imm_ GUARDED_BY(mutex_);  // Memtable being compacted

mem_可读可修改,imm_是只读的,持久化到磁盘的就是imm_
当我们写入KV时,数据都是先写入到mem_中:

...
if (status.ok())
 {
     status = WriteBatchInternal::InsertInto(write_batch, mem_);
 }
...

当mem_的大小达到以下条件时

(mem_->ApproximateMemoryUsage() > options_.write_buffer_size

mem_则转变为imm_,并新建一个新mem_。

 ...
 
 imm_ = mem_;
 has_imm_.store(true, std::memory_order_release);
 mem_ = new MemTable(internal_comparator_);
 mem_->Ref();
 
 ...

新生存的imm_会通过方法DBImpl::MaybeScheduleCompaction()持久到磁盘。

流程

Minjor Compaction的处理是在方法DBImpl::CompactMemTable()中实现的。
大致流程分为三步:

  1. 将Immutable落地生成SSTable文件、同时将文件信息放入Table_Cache中;
  2. 生成新的Version文件;
  3. 删除无用文件。

源码不多,实现如下:

void DBImpl::CompactMemTable() {
  mutex_.AssertHeld();
  assert(imm_ != nullptr);

  // Save the contents of the memtable as a new Table
  VersionEdit edit;
  Version* base = versions_->current();
  base->Ref();
  //1、落地生存新的SSTable文件。
  Status s = WriteLevel0Table(imm_, &edit, base);
  base->Unref();

  if (s.ok() && shutting_down_.load(std::memory_order_acquire)) {
    s = Status::IOError("Deleting DB during memtable compaction");
  }

  // Replace immutable memtable with the generated Table
  if (s.ok()) {

	//2、记录VersionEdit信息,
	//   通过LogAndApply()生存新的Version。
	//LogAndApply()还做了以下事情:
    //1)记录了compaction_score_最高的那一层的level及score。
	//2)检测更新manifest和Current文件。
    edit.SetPrevLogNumber(0);
    edit.SetLogNumber(logfile_number_);  // Earlier logs no longer needed
	
    s = versions_->LogAndApply(&edit, &mutex_);
  }

  if (s.ok()) {
    // Commit to the new state
    imm_->Unref();
    imm_ = nullptr;
    has_imm_.store(false, std::memory_order_release);
	//3、因为进行了Compact,此处主要涉及到logFile、Manifest、Current,
	//   所以调用此方法,对已经无用的文件进行删除。
    DeleteObsoleteFiles();
  } else {
    RecordBackgroundError(s);
  }
}

这里着重讲解下方法WriteLevel0Table()

//将Memtable落地为SSTable。
Status DBImpl::WriteLevel0Table(MemTable* mem, VersionEdit* edit,
                                Version* base) {
  mutex_.AssertHeld();
  const uint64_t start_micros = env_->NowMicros();
  FileMetaData meta;
  //获取新SSTable的文件名即FileNum
  meta.number = versions_->NewFileNumber();
  //保存此File,防止被删除
  pending_outputs_.insert(meta.number);
  //对此Memable创建访问的迭代器
  Iterator* iter = mem->NewIterator();
  Log(options_.info_log, "Level-0 table #%llu: started",
      (unsigned long long)meta.number);

  Status s;
  {
    mutex_.Unlock();
	//按SSTable格式生存SSTable文件到磁盘,
	//并将SSTable文件加入到table_cache_中
    s = BuildTable(dbname_, env_, options_, table_cache_, iter, &meta);
    mutex_.Lock();
  }

  Log(options_.info_log, "Level-0 table #%llu: %lld bytes %s",
      (unsigned long long)meta.number, (unsigned long long)meta.file_size,
      s.ToString().c_str());
  delete iter;
  //文件已生存,可删除此记录了。
  pending_outputs_.erase(meta.number);

  // 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 != nullptr) {

	  //新生存的SSTable文件,不一定都放在level-0层,有可能是level-1或者level-2层,
	  //但最多是level-2层。此方法就是根据最小和最大key,找到需要放此SSTable的level。
      level = base->PickLevelForMemTableOutput(min_user_key, max_user_key);
    }

	//通过VersionEdit记录新增的SSTable,用于后续产生新的Version。
    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;
}
总结

本篇主要是讲解的minor Compaction,minor Compaction作用就是要快速的将内存中的MemTable落地到磁盘生成SSTable文件,整个过程中并未考虑到不同SSTable文件直接的key的顺序问题。所以这对读是不友好的,为了解决这种SSTable文件之间key的重叠文件,major Compation就出现了,讲解留在下一篇。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值