leveldb简单架构 & 编码规则

KV引擎-LevelDB

LevelDB作为单机kv、基于LSM树的存储引擎, 其特点是高效,代码简洁而优美。在项目中的持久化数据的需求上目前既定使用LevelDB进行操作,下面了解下整体架构和部分细节实现。

整体架构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CgZZEwRq-1666144013586)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5c3f72e102bc4920b4bd5997205c5699~tplv-k3u1fbpfcp-watermark.image?)]

从写入流程来分析

  • WAL, 就是write Ahead Log, 用于保证数据的 持久性
  • MemTable, 内存存储结构对数据进行暂时的存储,内部的实现通过SkipList实现。当MemTable达到一定的大小之后转换为Immutable Table等待后台线程写入磁盘
  • SSTable, 通过Compaction生成的SSTable,分为不同的Level,因此该存储引擎被称为LevelDB
  • Manifest, 记录SSTable 的变更

亮眼1:数据编码压缩

整形定长数字编码

LevelDB中定长整型数字的编码,分为32bit & 64bit,下面着重分析32bit。

将定长的数字按照小端的方式进行顺序的编码,我们进行32bit整型的编码

🌰:首先看作是4个8位的数字:4,2,5,6

  • 按照小端的顺序的话,buf[0]存储的就是6对应的数据
  • 由于是小端,我们每次取的是最后面的8位,下一步先右移8位再取
  • 同上
//低版本的PUT。。。直接将内容写入缓冲区
//要求:dst需要拥有足够的空间
​
inline void EncodeFixed32(char* dst, u_int32_t value) {
    //类型转换,底层进行解释的不同,解释为:按照8位的类型进行解释
    uint8_t* const buffer = reinterpret_cast<uint8_t>(dst);
​
        /*
            每次都会将最后面的一个字节清除掉,小端,存储到buf中
            高地址---------低地址        
                4  2  5  6
        buf[0]:          |
​
        buf[1]:       |
​
        buf[2]:    |
​
        buf[3]: |
​
        */
    buffer[0] = static_cast<uint8_t>(value);
    buffer[1] = static_cast<uint8_t>(value >> 8);
    buffer[2] = static_cast<uint8_t>(value >> 16);
    buffer[3] = static_cast<uint8_t>(value >> 24);
}
​
inline void EncodeFixed64(char* dst, uint64_t value) {
  uint8_t* const buffer = reinterpret_cast<uint8_t*>(dst);
​
  //同上述函数,将内容解析到buf中
  buffer[0] = static_cast<uint8_t>(value);
  buffer[1] = static_cast<uint8_t>(value >> 8);
  buffer[2] = static_cast<uint8_t>(value >> 16);
  buffer[3] = static_cast<uint8_t>(value >> 24);
  buffer[4] = static_cast<uint8_t>(value >> 32);
  buffer[5] = static_cast<uint8_t>(value >> 40);
  buffer[6] = static_cast<uint8_t>(value >> 48);
  buffer[7] = static_cast<uint8_t>(value >> 56);
}
​

整形变长编码

当整型值较小时,LevelDB支持将其编码为变长整型,以减少其空间占用(对于值与类型最大值接近时,变长整型占用空间反而增加)。

对于变长整型编码,LevelDB需要知道该整型编码的终点在哪儿。因此,LevelDB将每个字节的最高位作为标识符,当字节最高位为1时表示编码未结束,当字节最高位为0时表示编码结束。因此,LevelDB的整型变长编码每8位用来表示整型值的7位。因此,当整型值接近其类型最大值时,变长编码需要额外一字节来容纳原整型值。

亮眼2:跳表实现MemTable

LevelDB中跳表
基本概述

levelDB中存储在内存中的数据就是存储在Memtable中的, 其中Memtable底层的数据结构就是基于 跳表来实现的。

其中Memtable会有很频繁的插入和查询的操作,删除操作被模拟为是插入一个带有(删除)标签的数据,需要支持遍历操作

多线程的支持

多线程进行操作的时候我们需要保证的一些:

Writes require external synchronization, most likely a mutex.

Reads require a guarantee that the SkipList will not be destroyed

  • Write:修改跳表的时候对用户进行加锁🔒
  • Read:访问跳表的时候保证跳表不会被销毁掉

通过原子性的操作,使得能够实现 读读并发,读写并发线程安全, 但是 写写并发需要使用者自行维护

leveldb约定

  • node不会被删除除非整个跳表结构都被销毁掉
  • node节点除了next指针之外都是不变的
跳表的实现

参考代码

leveldb实现解析 淘宝-核心系统研发-存储 那岩 neveray@gmail.com 2011-12-13 目录 一、 代码目录结构 ....................................................................... 1 1. doc/ ............................................................................ 1 2. include/leveldb/ ................................................................. 1 3. db/ ............................................................................. 1 4. table/........................................................................... 1 5. port/ ........................................................................... 1 6. util/ ........................................................................... 1 7. helper/memenv/ ................................................................... 1 二、 基本概念 .......................................................................... 1 1. Slice (include/leveldb/slice.h) .................................................. 1 2. Option (include/leveldb/option.h) .............................................. 2 3. Env (include/leveldb/env.h util/env_posix.h) .................................... 3 4. varint (util/coding.h) ........................................................... 3 5. ValueType (db/dbformat.h) ...................................................... 3 6. SequnceNnumber (db/dbformat.h) ................................................. 4 7. user key......................................................................... 4 8. ParsedInternalKey (db/dbformat.h) .............................................. 4 9. InternalKey (db/dbformat.h) ...................................................... 4 10. LookupKey (db/dbformat.h) ........................................................ 4 11. Comparator (include/leveldb/comparator.h util/comparator.cc) .................... 4 12. InternalKeyComparator (db/dbformat.h) ............................................ 5 13. WriteBatch (db/write_batch.cc) ................................................. 5 14. Memtable (db/memtable.cc db/skiplist.h) .......................................... 5 15. Sstable (table/table.cc) ......................................................... 5 16. FileMetaData (db/version_edit.h) ............................................... 5 17. block (table/block.cc) ........................................................... 6 18. BlockHandle(table/format.h) ...................................................... 6 19. FileNumber(db/dbformat.h) ...................................................... 6 20. filename (db/filename.cc) ........................................................ 6 21. level-n (db/version_set.h) ....................................................... 7 22. Compact (db/db_impl.cc db/version_set.cc) ........................................ 7 23. Compaction(db/version_set.cc) .................................................... 7 24. Version (db/version_set.cc) ...................................................... 8 25. VersionSet (db/version_set.cc) ................................................. 9 26. VersionEdit(db/version_edit.cc) ................................................. 10 27. VersionSet::Builder (db/version_set.cc) ......................................... 11 28. Manifest(descriptor)(db/version_set.cc)...................................... 12 29. TableBuilder/BlockBuilder(table/table_builder.cc table/block_builder.cc) ......... 12 30. Iterator (include/leveldb/iterator.h) ........................................... 12 三、 存储结构的格式定义与操作 .......................................................... 12 1. memtable (db/skiplist.h db/memtable) ............................................ 12 2. block of sstable (table/block_builder.cc table/block.cc) ......................... 14 3. sstable (table/table_bulder.cc/table.cc) ........................................ 16 4. block of log (db/log_format.h db/log_writer.cc db/log_reader.cc) .............. 18 5. log (db/log_format.h db/log_writer.cc db/log_reader.cc) ........................ 18 6. cache(util/cache.cc) .......................................................... 19 7. Snapshot (include/leveldb/snapshot.h) ......................................... 19 8. Iterator (include/leveldb/iterator.h) ........................................... 19 四、 主要流程 ......................................................................... 24 1. open ........................................................................... 24 2. put ............................................................................ 25 3. get ............................................................................ 25 4. delete.......................................................................... 26 5. snapshot........................................................................ 26 6. NewIterator ..................................................................... 26 7. compact......................................................................... 26 五、 总结 ............................................................................. 30 1. 设计/实现中的优化 ............................................................... 30 2. 可以做的优化 .................................................................... 31
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值