LevelDB 源码分析 (一) | 前沿和基本组件
What is LevelDB
LevelDB 是 KV 型数据库,为 BSD 协议,为 Leveling+分区
实现的 LSM 代表,适合写多读少。
特性
- Key Value 支持任意 Byte 类型数组,不单单支持字符串
- 为持久化存储的 KV 系统,大部分数据存在磁盘上
- 按照 key 值顺序存储数据,按照用户定义的比较函数进行排序
- 操作接口简单,包括写/读记录以及删除记录,也支持针对多条操作的原子批量操作
- 支持 snapshot,读写操作互不影响
- 支持 snappy 压缩,I/O 效率高
源码编译
直接 clone
1
git clone https://github.com/google/leveldb.git
initialize submodule issues#1004
1
2
3
4
5# 一步到位
git clone --recurse-submodules https://github.com/google/leveldb.git
# without re-cloning
git submodule update --init --recursive编译
1
2
3
4
5
6
7cd leveldb
mkdir -p build && cd build
# Release
cmake -DCMAKE_BUILD_TYPE=Release .. && cmake --build .
# Debug 方便跟踪还是 Debug 伐
cmake -DCMAKE_BUILD_TYPE=Debug .. && cmake --build .为方便将 levelDB 加入到系统库
1
2
3
4
5# Linux
cp -r ./include/leveldb /usr/include/
cp build/libleveldb.a /usr/local/lib/
# MacOS waiting
基本组件
字节序 Endian
一般都是小端序,将低序字节存在起始位置的为小端序,反之为大端序。以 short 2B 数据作测试:
1 | /* RETURN "Little Endian" */ |
slice
slice 为 levelDB 自定义的数据结构,在 include\leveldb\slice.h
中,不用 string
的原因是 CPP 中 string 为拷贝变量,不支持 remove_prefix, starts_with 的操作,不灵活。
1 | // Snippets of `slice.h` |
status
status.h
用于记录 levelDB 中状态信息,保存错误码和对应的字符串错误信息(不支持自定义)。基本组成为:
Status 具有特色的私有变量为:
1 | private: |
具体实现为:
1 | /*status.cc*/ |
编码
levelDB 中分为定长和变长编码,变长编码目的是为了减少空间占用,基本思想为:每一个 Byte 最高位 bit 用 0/1 表示该整数是否结束,用剩余 7-bit 表示实际的数值,在 protobuf 中被广泛使用。
if-else 根据数值 v 来判断是否需要继续变长。B 作为最高位来表示整数是否结束。
1 | /* util\coding.cc */ |
Option
- Option 记录了 levelDB 中的参数信息,用来控制 levelDB 的控制信息
- 通用(如 block 数据大小和读写设置):
options.h
GitHub - LSM存储设置:
dbformat.h
GitHub
skiplist
常规线段跳表
- 定义
skiplist 用于代替平衡树,可以看作是并联的有序链表。skiplist 通过概率保证平衡,平衡树采用严格的旋转来保证平衡,因此 skiplist 比较容易实现,并且相比平衡树有着较高的运行效率。
Redis 中也是 skiplist,其默认最大的 level 为64
db/skiplist.h
引用
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Sicilienne!
评论
Valine# ValineDisqus