Ch04-LevelDB 之 MemTable

Ch04-LevelDB 之 MemTable

May 12, 2022
LevelDB
leveldb

MemTable

1. Immutable VS Mutable #

本质上都是 MemTable,只是其定义的变量扮演的角色不同罢了,有点类似于 double buffer 的两个 buffer 之间的关系。

namespace leveldb {
class DBImpl : public DB {
  public:

  private:
    MemTable* mem_;
    MemTable* imm_ GUARDED_BY(mutex_);
  }
}

2. 数据结构定义 #

// db/memtable.h
namespace leveldb {
class MemTable {
public:
  void Add(SequenceNumber seq, ValueType type, const Slice& key, const Slice& value);
  bool Get(const LookupKey& key, std::string* value, Status* s);

private:
  KeyComparator comparator_;

  typedef SkipList<const char*, KeyComparator> Table;
  Table table_;
};
}
// db/skiplist.h

namespace leveldb {
template <typename Key, class Comparator>
class SkipList {
public:
  void Insert(const Key& key);
  bool Contains(const Key& key) const;

  class Iterator {
    void Next();
    void Prev();
    void Seek(const Key& target);
  }

private:
  Comparator const compare_;
  Node* const head_;
};

template <typename Key, class Comparator>
struct SkipList<Key, Comparator>::Node {
  Key const key;
  Node* Next(int n)

private:
 std::atomic<Node*> next_[1];
}

3. 原理说明 #

本质上是对 SkipList 的再封装,所以它的 Add(...)Get(...) 操作本质上就是对 SkipList 的操作。SkipList 的原理,这里不去详细说明,网上有很多,自行搜索便是。

4. 内存分配 #

借由 Arena 完成,且不会独自回收内存。

5. 构造说明 #

插入数据的时候,会首先将 key 和 value 编码成下述所示的字符串,再构造成 SkipList::Node 插入到 SkipList 中。写操作的核心部分由 SkipList::Insert(...) 完成。

put

读取数据的时候,Node 的 key 构造规则会略有不同,仅仅会构造前半部分,如下所示。读取操作的核心部分由 SkipList::Iterator::Seek(…) 完成。

get