五、.ldb文件
关于ldb文件说明:
1)ldb文件是按照block存储,一个block默认大小为4KB,当内存数据增长到4KB则进行写文件操作。
2)从leveldb v1.14版本开始,数据存储到了后缀名为ldb文件中,不在存储到sst文件中。
3)一个ldb文件包含:data block,filter block,meta index block,data index block以及footer。其中filter block是可选的。
存储格式整体如下:
5.1 Block-Entry格式
所有的Block格式都是相同的,一个Block默认大小为4KB,当Block所占内存空间大于4KB则flush到文件中。一个Block可以包含多个entry,每个entry只包含三个元素:
字段名 | 说明 | 备注 |
Block Contents | block存储的内容,内容格式由上层决定。这里可以参考下面章节 | 不定长,具体长度保存在 data index block中 |
Compression Type | 为了减少磁盘空间,可对数据进行压缩,取值为:kNoCompression、kSnappyCompression | 1字节 |
CRC | crc数据校验和 | 4字节 |
5.2 Data Block
5.2.1 重启点
leveldb为了提升性能,抽象出一个重启点概念,感觉挺玄乎其实就是偏移量.一个Block至少有一个重启点.那么重启点等于什么呢? 等于16个Block-Entry大小.举例说明:
例子1: 一个block存储了19条Block-Entry,每条Block-entry是64字节,那么重启点一共有两个分别为0,16*64
例子2: 一个block存储了34条Block-Entry,每条Block-entry是64字节,那么重启点一共有三个分别为0,16*64,32*64
例子3: 一个block存储了1条Block-Entry,这条Block-Etnry是5KB字节,那么重启点只有一个是0
说明:
1) 一个Block至少有一个重启点,其重启点值为0
2) 一个Block默认大小是4KB,如果所有Block-Entry所占内存字节大于4KB则将这个Block刷新到文件中,所以会出现例子3的场景
5.2.2 Block Contents格式
上面介绍了重启点,下面介绍在Data Block类型下Block Contents格式如下所示:
字段说明:
序号 | 字段 | 说明 | 备注 |
1 | key值相同部分大小 | 本条记录相对于上一条记录的key,有多少字符是相同的。 | Varint32类型 |
2 | key值不同部分大小 | 本条记录相对于上一条记录的key,有多少字符是不同的。 | Varint32类型 |
3 | value大小 | 本条记录value内容大小。 | Varint32类型 |
4 | key值不同的部分 实际内容 | key值不同内容 | 字节数组 |
5 | value内容 | 本条记录value实际内容 | 至此1-5构成一条Record |
6 | 重启点值以及重启点个数 |
举例说明,分别插入如下记录:
记录 | key值相同部分大小 | key值不同部分大小 | value大小 | key不同内容 | value内容 |
helloworld:my-helloworld | 0 | 10 | 13 | helloworld | my-helloworld |
helloleveldb:my-helloleveldb | 5 | 7 | 15 | leveldb | my-helloleveldb |
myhello:good | 0 | 7 | 4 | myhello | good |
helloworld2:my-helloworld2 | 0 | 11 | 14 | helloworld2 | my-helloworld2 |
5.3 、Filter Block
该部分是可选的,如果在创建db的时候指定的Options中设置了filter_policy,我们可以自定义用户过滤策略,目前leveldb提供的过滤策略为Bloom Filter。 当指定了filter_policy那么在生成ldb文件时就会存储Filter Block相关信息。
5.4、Meta Index Block
该部分是主要用于后续leveldb扩展使用,目前元信息比较少,主要用于保存filter policy名字。
5.5、Data Index Block
index block存储格式与data block存储格式是一样的,可参考data block格式,此处不再放图展示.一个ldb文件中存在多个Data Block,每个Data Block在ldb中位置以及DataBlock实际大小都保存在Data Index Block中。
1)Data Index Block有且只有一个。
2)Data Index Block中每一个Entry对应一个Data Block元信息,元信息包含:Data Block最大InternalKey,Data Block在ldb文件中偏移量以及DataBlock实际大小。所以可以将Data Index Block理解为Data Block元信息管理者。
5.6、Footer
Footer的大小始终是48字节,最后8字节是魔鬼数字,保证文件有效性,存储结构在已经给出,具体字段参数含义如下:
字段 | 含义 |
meta index offset | meta index block在ldb文件中偏移量,类型为varint64 |
meta index size | meta index block大小,类型为varint64 |
data index offset | data index block在ldb文件中偏移量,类型为varint64 |
data index size | data index block大小,类型为varint64 |
padding | 索引相关一共占用40字节,padding是为了补齐 |
MagicNumber | 8字节,魔鬼数字 |
leveldb在读取ldb文件时会从文件尾部偏移48字节,用于读取ldb文件元数据,并对各个字段进行解析。
六、总结
花两个篇博客来阐明leveldb存储结构,希望能够帮助大家缕清思路。后面开始介绍源码相关内容。