leveldb源码剖析1.4–基础概述之存储格式

引言

前面讲了leveldb的关键文件,现在主要介绍各类关键文件的数据格式,这对我们阅读和理解leveldb源码是很有必要的。特别地,下面所有数字都是小端存储。

1 log文件

1.1 WriteBatch

leveldb将Put/Delete/Write封装成WriteBatch对象,然后将WriteBatch序列化后写入log文件。其中WriteBatch序列化后的格式如下:
在这里插入图片描述

  • Sequeue:所有的写入数据操作都是严格排序的。该字段为第一个KV操作的序号,下一个WriteBatch的Sequeue就是该值加上Count。
  • Count:该Batch包含的KV操作数量。
  • ValueType:KV操作类型,删除数据为0,否则为1。
  • KeyLength:Key值长度。
  • Key Content:Key值,长度等于KeyLength。
  • ValueLength:Value值长度。
  • Value Content:Value值,长度等于ValueLength。

1.2 Log格式

每个WriteBatch按照不超过(32K-7Byte)大小以帧写入log文件,其中7 Byte为帧头。同时,它以32K为一个数据单位或者说数据块对齐,当多个不足(32K-7Byte)的WriteBatch有序写入时,若最后剩余字节小于7 Byte,那么它就会以“0x00”填充,即确保帧头必须落在一个32K范围内。
Log文件帧格式如下:
在这里插入图片描述

  • CRC:WriteBatch frame Datas的校验码。
  • Data Length:WriteBatch Frame Datas的长度。
  • RecordType:为0表示是一个空数据;为1表示是一个完整的WriteBatch,没有分帧;为2表示是WriteBatch第一个分帧;为3表示WriteBatch的中间分帧;为4表示是WriteBatch的最后一个分帧。
  • WriteBatch Frame Datas:帧内容。

2 sstable文件

sstable是持久化文件,其总体格式如下:
在这里插入图片描述
整个文件分为五部分:Data Block、Meta Block、Meta Index Block、Data Index Block和Footer。其中Meta Index Block指向每个Meta Block,目前meta只有一种,即过滤器。所以,Meta Block目前只有一个;同样,Data Index Block指向每个Data Block。

2.1 Data Block

Data Block是实际存储数据的块,在归并写入sstable文件过程中,每当写入的数据缓存达到大于或等于4K的时候,就会产生一个Data Bock并写入sstable文件。
在这里插入图片描述
首先,整个Data Block单元由Compression Data、CompressionType和CRC三部分组成。其中CompressionType为压缩类型,目前有kNoCompression和kSnappyCompression两种,即没有压缩和snappy方式压缩;CRC为判断数据完整性的校验码。
然后,Compression Data又有多个KV Group组成,后面追加每个KV Group在当前Data Block的起始偏移字节(即KV Group Index,末尾再加4字节的KV Group个数。每个KV Group由不超过16个KV数据结构,即每16个KV组成一个KV Group,直到最后剩余数目小于等于16个组成最后一个KV Group。
最后,每个KV结构由4字节的Key Shared Size、4字节的Key non Shared Size、4字节的Value Size和Key on Shared Content以及Value Content。其中Key Shared Size是指与上一个Key中前半部分相同内容长度,例如before key=“12345”、after key=“12367”,那么after key对应的Key Shared Size=3、Key non Shared Size=2;此外,这里的key是InternalKey而非UserKey。

2.2 Meta Block

目前Meta Block只存储Filter,也就是为了判断在某个Block中是否存在某个Key的位图。与Data Block不同的是Filter Block只有一个。
在这里插入图片描述
与Data Block类似,整个单元由Compression Data、CompressionType和CRC三部分组成。只是Compression Data为固定值kNoCompression。
Compression Data由三部分组成,前面连续的Filter Bitmap数组、中间的Filter起始偏移、末尾的Filter起始偏移和FilterBaseLg,其中FilterBaseLg为固定值11。
每个Data Block对应一个Filter Bitmap,但Filter Index与Filter Bitmap却不是一对一的。假设某个Data Block在文件内的起始偏移为9K、长度为5K,那么第4个(即9K/2K取整)Filter Index指向该Data Block对应的Filter Bitmap的开始,此外,后面还有2个(即14K/2K - 4 -1)Filter Index指向Filter Bitmap的末尾。特别地,2K也就是1左移FilterBaseLg位的值。

2.3 Meta Index Block

Meta Index Block与Data Block结构完全一致,也是存储KV。特殊的是:Meta Index Block中的key为固定值“filter.”+filterName、value是Meta Block的起始文件位置和块大小。Value格式如下:
在这里插入图片描述
注:Meta Index Block目前只有一项。

2.4 Data Index Block

同样,Data Index Block与Data Block结构完全一致,也是存储KV。其key为大于或等于对应的Data Block的最后一个key值、同时小于或等于下一个Data Block的第一个key值;value是对应的Data Block的起始文件位置和块大小。Value格式与Meta Index Block的Value完全一致,格式如下:
在这里插入图片描述

2.5 Footer

Footer由三段组成,第一段指向第一个Meta Index Block的文件内偏移和所有Meta Index Block数据大小;第二段指向第一个Data Index Block的文件内偏移和所有Data Index Block数据大小;第三段是先将kTableMagicNumber的高32位按四字节存储、再将低32位按四字节存储。其结构如下:
在这里插入图片描述
注:kTableMagicNumber为固定值,即0xdb4775248b80fb57。

3 manifest文件

manifest也是一种log文件,大的格式与Log文件相同,里面存储的数据稍微比WriteBatch复杂。manifest每帧格式如下:
在这里插入图片描述
注:Data Content内部分为8种数据。如果某一Tag的数据不存在,就会空着,例如Tag=3的不存在、Tag=4的存在,那么Tag=9的数据段后面就跟着Tag=4的数据。

4 current文件

current文件就是一个文本文件,里面记录着当前manifest文件全名并以“\n”结尾。

猜你喜欢

转载自blog.csdn.net/fs3296/article/details/107813585
今日推荐