LevelDB的memtable(内存中的数据)
LevelDB的memtable(内存中的数据)
存储在内存中的memtable的结构是跳表,有一个逻辑,当memtable的size达到了阈值后,就会将memtable转变为只读的imutable memtable,然后新生成一个memtable
代码文件:db/memtable.h,db/memtable.cc
namespace leveldb {
class InternalKeyComparator;
class MemTableIterator;
class MemTable {
public:
// MemTables are reference counted. The initial reference count
// is zero and the caller must call Ref() at least once.
// 构造函数的参数就是比较器
explicit MemTable(const InternalKeyComparator& comparator);
MemTable(const MemTable&) = delete;
MemTable& operator=(const MemTable&) = delete;
// Increase reference count.
void Ref() { ++refs_; }
// Drop reference count. Delete if no more references exist.
void Unref() {
--refs_;
assert(refs_ >= 0);
if (refs_ <= 0) {
delete this;
}
}
// Returns an estimate of the number of bytes of data in use by this
// data structure. It is safe to call when MemTable is being modified.
// 这个函数是记录内存池的用量,其实就是memtable的大小
size_t ApproximateMemoryUsage();
// Return an iterator that yields the contents of the memtable.
//
// The caller must ensure that the underlying MemTable remains live
// while the returned iterator is live. The keys returned by this
// iterator are internal keys encoded by AppendInternalKey in the
// db/format.{h,cc} module.
// 在memtable封装了一个跳表的接口,通过这个迭代器,可以操作memtable的跳表
Iterator* NewIterator();
// Add an entry into memtable that maps key to value at the
// specified sequence number and with the specified type.
// Typically value will be empty if type==kTypeDeletion.
// 将key和value转换成InternalKey后存储在跳表里面
void Add(SequenceNumber seq, ValueType type, const Slice& key,
const Slice& value);
// If memtable contains a value for key, store it in *value and return true.
// If memtable contains a deletion for key, store a NotFound() error
// in *status and return true.
// Else, return false.
// 查询memtable,其实就是查询跳表
bool Get(const LookupKey& key, std::string* value, Status* s);
private:
friend class MemTableIterator;
friend class MemTableBackwardIterator;
struct KeyComparator {
const InternalKeyComparator comparator;
explicit KeyComparator(const InternalKeyComparator& c) : comparator(c) {}
int operator()(const char* a, const char* b) const;
};
typedef SkipList<const char*, KeyComparator> Table;
~MemTable(); // Private since only Unref() should be used to delete it
KeyComparator comparator_;
int refs_;
Arena arena_;
Table table_;
};
} // namespace leveldb
namespace leveldb {
// p+5就是limit,ptr>=p && ptr<p+5;所以一共就是读取前面4个字节
static Slice GetLengthPrefixedSlice(const char* data) {
uint32_t len;
const char* p = data;
// 其实正常情况下,返回的p就是等于之前的p+5,也就是数据开始的地方
p = GetVarint32Ptr(p, p + 5, &len); // +5: we assume "p" is not corrupted
// 由数据长度,读取数据,然后返回数据
return Slice(p, len);
}
MemTable::MemTable(const InternalKeyComparator& comparator)
// table_就是跳表,他的构造函数函数就是比较器和内存池
: comparator_(comparator), refs_(0), table_(comparator_, &arena_) {}
MemTable::~MemTable() { assert(refs_ == 0); }
// 返回内存池的用量,其实就是memtable的大小
size_t MemTable::ApproximateMemoryUsage() { return arena_.MemoryUsage(); }
int MemTable::KeyComparator::operator()(const char* aptr,
const char* bptr) const {
// Internal keys are encoded as length-prefixed strings.
Slice a = GetLengthPrefixedSlice(aptr);
Slice b = GetLengthPrefixedSlice(bptr);
return comparator.Compare(a, b);
}
// Encode a suitable internal key target for "target" and return it.
// Uses *scratch as scratch space, and the returned pointer will point
// into this scratch space.
static const char* EncodeKey(std::string* scratch, const Slice& target) {
scratch->clear();
PutVarint32(scratch, target.size());
scratch->append(target.data(), target.size());
return scratch->data();
}
// 重新封装了一个迭代器,就是一些操作跳表的接口
class MemTableIterator : public Iterator {
public:
explicit MemTableIterator(MemTable::Table* table) : iter_(table) {}
MemTableIterator(const MemTableIterator&) = delete;
MemTableIterator& operator=(const MemTableIterator&) = delete;
~MemTableIterator() override = default;
bool Valid() const override { return iter_.Valid(); }
void Seek(const Slice& k) override { iter_.Seek(EncodeKey(&tmp_, k)); }
void SeekToFirst() override { iter_.SeekToFirst(); }
void SeekToLast() override { iter_.SeekToLast(); }
void Next() override { iter_.Next(); }
void Prev() override { iter_.Prev(); }
Slice key() const override { return GetLengthPrefixedSlice(iter_.key()); }
Slice value() const override {
Slice key_slice = GetLengthPrefixedSlice(iter_.key());
return GetLengthPrefixedSlice(key_slice.data() + key_slice.size());
}
Status status() const override { return Status::OK(); }
private:
MemTable::Table::Iterator iter_;
std::string tmp_; // For passing to EncodeKey
};
Iterator* MemTable::NewIterator() { return new MemTableIterator(&table_); }
void MemTable::Add(SequenceNumber s, ValueType type, const Slice& key,
const Slice& value) {
// Format of an entry is concatenation of:
// key_size : varint32 of internal_key.size()
// key bytes : char[internal_key.size()]
// value_size : varint32 of value.size()
// value bytes : char[value.size()]
// 由user_key到internalkey的大小,其实就是user_key.size()+8
size_t key_size = key.size();
size_t val_size = value.size();
size_t internal_key_size = key_size + 8;
// VarintLength的返回结果是int编码后的所用的长度,就是低7位存值,第8位为1说明数据没结束
// encoded_len就是internal+value以及他们各自长度的所占的总字节数
const size_t encoded_len = VarintLength(internal_key_size) +
internal_key_size + VarintLength(val_size) +
val_size;
// 向内存池申请内存
char* buf = arena_.Allocate(encoded_len);
// 编码internalkey的长度
char* p = EncodeVarint32(buf, internal_key_size);
// 写入user_key
std::memcpy(p, key.data(), key_size);
p += key_size;
// 写入序号和类型
EncodeFixed64(p, (s << 8) | type);
p += 8;
// 编码value的长度
p = EncodeVarint32(p, val_size);
// 写入value
std::memcpy(p, value.data(), val_size);
assert(p + val_size == buf + encoded_len);
// 将编码后的数据插入跳表
table_.Insert(buf);
}
bool MemTable::Get(const LookupKey& key, std::string* value, Status* s) {
// 获取memtable_key,就是长度加user_key+序号+类型
Slice memkey = key.memtable_key();
// 迭代器
Table::Iterator iter(&table_);
//
iter.Seek(memkey.data());
if (iter.Valid()) {
// 下面就是查出的所有结果
// entry format is:
// klength varint32
// userkey char[klength]
// tag uint64
// vlength varint32
// value char[vlength]
// Check that it belongs to same user key. We do not check the
// sequence number since the Seek() call above should have skipped
// all entries with overly large sequence numbers.
const char* entry = iter.key();
uint32_t key_length;
const char* key_ptr = GetVarint32Ptr(entry, entry + 5, &key_length);
if (comparator_.comparator.user_comparator()->Compare(
Slice(key_ptr, key_length - 8), key.user_key()) == 0) {
// 比较得到user_key相同,说明在memtable中找到了正确的key
// Correct user key
// 获取序号加类型
const uint64_t tag = DecodeFixed64(key_ptr + key_length - 8);
switch (static_cast<ValueType>(tag & 0xff)) {
case kTypeValue: {
Slice v = GetLengthPrefixedSlice(key_ptr + key_length);
value->assign(v.data(), v.size());
return true;
}
case kTypeDeletion:
// 这是被删掉的key
*s = Status::NotFound(Slice());
return true;
}
}
}
return false;
}
} // namespace leveldb
浙公网安备 33010602011771号