博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
深入 LevelDB 数据文件 SSTable 的结构
阅读量:2440 次
发布时间:2019-05-10

本文共 3296 字,大约阅读时间需要 10 分钟。

LevelDB 的键值对内容都存储在扩展名为 sst 的 SSTable 文件中,SSTable 的磁盘文件结构比较复杂,读者在阅读本节之前要做好心理准备。如果有任何看得不明白的地方,一定要在下方的问答区及时提问。

640?wx_fmt=png
图片

SSTable 文件的内容分为 5 个部分,Footer、IndexBlock、MetaIndexBlock、FilterBlock 和 DataBlock。其中存储了键值对内容的就是 DataBlock,存储了布隆过滤器二进制数据的是 FilterBlock,DataBlock 有多个,FilterBlock 也可以有多个,但是通常最多只有 1 个,之所以设计成多个是考虑到扩展性,也许未来会支持其它类型的过滤器。另外 3 个部分为管理块,其中 IndexBlock 记录了 DataBlock 相关的元信息,MetaIndexBlock 记录了过滤器相关的元信息,而 Footer 则指出 IndexBlock 和 MetaIndexBlock 在文件中的偏移量信息,它是元信息的元信息,它位于 sstable 文件的尾部。下面我们至顶向下挨个分析每个结构

Footer 结构

它的占用空间很小只有 48 字节,内部只存了几个字段。下面我们用伪代码来描述一下它的结构

// 定义了数据块的位置和大小struct BlockHandler {  varint offset;  varint size;}struct Footer {  BlockHandler metaIndexHandler;  // MetaIndexBlock的文件偏移量和长度  BlockHandler indexHandler; // IndexBlock的文件偏移量和长度  byte[n] padding;  // 内存垫片  int32 magicHighBits;  // 魔数后32位  int32 magicLowBits; // 魔数前32位}

$ echo http://code.google.com/p/leveldb/ | sha1sumdb4775248b80fb57d0ce0768d85bcee39c230b61

Block 结构

除了 Footer 之外,其它部分都是 Block 结构,在名称上也都是以 Block 结尾。所谓的 Block 结构是指除了内部的有效数据外,还会有额外的压缩类型字段和校验码字段。

struct Block {  byte[] data;  int8 compressType;  int32 crcValue;}

crcValue = crc32(data, compressType)

DataBlock 结构

DataBlock 的大小默认是 4K 字节(压缩前),里面存储了一系列键值对。前面提到 sst 文件里面的 Key 是有序的,这意味着相邻的 Key 会有很大的概率有共同的前缀部分。正是考虑到这一点,DataBlock 在结构上做了优化,这个优化可以显著减少存储空间。

Key = sharedKey + unsharedKey

640?wx_fmt=png
图片

比如基准 Key 是 helloworld,那么 hellouniverse 这个 Key 相对于基准 Key 来说,它的 sharedKey 就是 hello,unsharedKey 就是 universe。

640?wx_fmt=png
图片

DataBlock 中存储的是连续的一系列键值对,它会每隔若干个 Key 设置一个基准 Key。基准 Key 的特点就是它的 sharedKey 部分是空串。基准 Key 的位置,也就是它在块中的偏移量我们称之为「重启点」RestartPoint,在 DataBlock 中会记录所有「重启点」位置。第一个「重启点」的位置是零,也就是 DataBlock 中的第一个 Key。

struct Entry {  varint sharedKeyLength;  varint unsharedKeyLength;  varint valueLength;  byte[] unsharedKeyContent;  byte[] valueContent;}struct DataBlock {  Entry[] entries;  int32 [] restartPointOffsets;  int32 restartPointCount;}

一个 DataBlock 的默认大小只有 4K 字节,所以里面包含的键值对数量通常只有几十个。如果单个键值对的内容太大一个 DataBlock 装不下咋整?

这里就必须纠正一下,DataBlock 的大小是 4K 字节,并不是说它的严格大小,而是在追加完最后一条记录之后发现超出了 4K 字节,这时就会再开启一个 DataBlock。这意味着一个 DataBlock 可以大于 4K 字节,如果 value 值非常大,那么相应的 DataBlock 也会非常大。DataBlock 并不会将同一个 Value 值分块存储。

FilterBlock 结构

如果没有开启布隆过滤器,FilterBlock 这个块就是不存在的。FilterBlock 在一个 SSTable 文件中可以存在多个,每个块存放一个过滤器数据。不过就目前 LevelDB 的实现来说它最多只能有一个过滤器,那就是布隆过滤器。

布隆过滤器用于加快 SSTable 磁盘文件的 Key 定位效率。如果没有布隆过滤器,它需要对 SSTable 进行二分查找,Key 如果不在里面,就需要进行多次 IO 读才能确定,查完了才发现原来是一场空。布隆过滤器的作用就是避免在 Key 不存在的时候浪费 IO 操作。通过查询布隆过滤器可以一次性知道 Key 有没有可能在里面。

640?wx_fmt=png
图片

单个布隆过滤器中存放的是一个定长的位图数组,该位图数组中存放了若干个 Key 的指纹信息。这若干个 Key 来源于 DataBlock 中连续的一个范围。FilterBlock 块中存在多个连续的布隆过滤器位图数组,每个数组负责指纹化 SSTable 中的一部分数据。

struct FilterEntry {  byte[] rawbits;}struct FilterBlock {  FilterEntry[n] filterEntries;  int32[n] filterEntryOffsets;  int32 offsetArrayOffset;  int8 baseLg;  // 分割系数}

// 每个 Key 占用 10bit 存放指纹信息options.SetFilterPolicy(levigo.NewBloomFilter(10))

MetaIndexBlock 结构

MetaIndexBlock 存储了前面一系列 FilterBlock 的元信息,它在结构上和 DataBlock 是一样的,只不过里面 Entry 存储的 Key 是带固定前缀的过滤器名称,Value 是对应的 FilterBlock 在文件中的偏移量和长度。

key = "filter." + filterName// value 定义了数据块的位置和大小struct BlockHandler {  varint offset;  varint size;}

640?wx_fmt=png
图片

IndexBlock 结构

它和 MetaIndexBlock 结构一样,也存储了一系列键值对,每一个键值对存储的是 DataBlock 的元信息,SSTable 中有几个 DataBlock,IndexBlock 中就有几个键值对。键值对的 Key 是对应 DataBlock 内部最大的 Key,Value 是 DataBlock 的偏移量和长度。不考虑 Key 之间的前缀共享,不考虑「重启点」,它的结构如下图所示

640?wx_fmt=png
图片

SSTable 的结构就讲到这里,下一节我们继续观察日志文件的结构

640?wx_fmt=png

转载地址:http://fvbqb.baihongyu.com/

你可能感兴趣的文章
Windows Vista内置趣味实用工具大搜罗(转)
查看>>
FreeBSD安装文件系统(转)
查看>>
最简单FreeBSD网关方案(转)
查看>>
Windows 98 多用户的管理(转)
查看>>
更改Windows XP 的日期和时间(转)
查看>>
windows2000中的“秘密武器”(三)(转)
查看>>
Linux程序应用开发环境和工具经验谈(转)
查看>>
Linux办公一条龙之电子表格Calc(转)
查看>>
在NETBSD上配置ADSL+IPF+IPNAT(转)
查看>>
Windows 98 使用维护向导(转)
查看>>
用win2000收发传真(转)
查看>>
Linux办公一条龙之初识OpenOffice(转)
查看>>
Linux上安装GCC编译器过程(转)
查看>>
使用Windows XP 的任务计划(转)
查看>>
Linux分区工具的使用方法(转)
查看>>
深入理解硬盘的Linux分区(转)
查看>>
循序渐进教你LINUX之软件配置方法(转)
查看>>
NetBSD 指导手册(转)
查看>>
打造FreeBSD桌面系统(2)(转)
查看>>
为你的 Windows 98 加把锁(转)
查看>>