二、levelDB整体框架,及memtable、log文件、immutable memtable

3、整体框架 和 6大组件

整体框架

图片是LevelDB运行一段时间后的存储模型快照,包括6个重要组件:

 

内存中:MemTable、Immutable MemTable

磁盘上:log文件、 Manifest文件、Current文件、SSTable文件

LevelDb除了这六个主要部分还有一些辅助的文件,但是以上六个文件和数据结构是LevelDb的主体构成元素。
其中:

MemTable:就是内存中的那棵树

SSTable:就是磁盘中的树,并且你会看到,分了level0,1,2,3好多层级,而每个层级里又有很多个.sst文件;

 

接下来每个组件,我们详细讲解一下;首先我们讲一下MemTatable。

3.1  Memtable   

 

我们看一下底层SkipList的数据结构,是怎么维护一个有序的Key序列:

我们对链表结构比较熟悉,对于跳表就很好理解了
从该有序表中搜索元素 < 23, 43, 59 > ,需要比较的次数分别为 < 2, 4, 6 >,总共比较的次数为 2 + 4 + 6 = 12 次。

有没有优化的算法吗? 我们把一些节点提取出来,作为索引。得到图3的结构:

 

总共比较的次数为 2 + 3 + 3 = 8 次,比之前减少了4次。
这里元素不多,体现不出优势,如果元素足够多,这种索引结构就能体现出优势来了。   

 

3.2  Log文件

写如速度高效的根本原因:
1,首先是将这条KV记录以顺序写的方式追加到log文件末尾,因为尽管这是一个磁盘读写操作,但是文件的顺序追加写入效率是很高的,所以并不会导致写入速度的降低;

2,如果写入log文件成功,那么将这条KV记录插入内存中的Memtable中,前面介绍过,Memtable只是一层封装,其内部其实是一个Key有序的SkipList列表,插入一条新记录的过程也很简单,即先查找合适的插入位置,然后修改相应的链接指针将新记录插入即可。完成这一步,写入记录就算完成了。

3,所以一个插入记录操作涉及一次磁盘文件追加写和内存SkipList插入操作这是为何levelDb写入速度如此高效的根本原因。

 

而前边讲的顺序写,提高写的效率,主要是指磁盘中,不同层级树的数据合并操作,而这个合并操作,是单独的线程在处理;

 

既然是存到磁盘,就会涉及到空间问题,那就会涉及到log的存储格式,以什么样的格式存储,更省空间,更合理,更高效?
接下来我们讲一下.log的文件格式

 

 

Log文件在磁盘上的存储格式:

•Log文件划分为固定长度的block, 每个block固定大小32KB;

•recode的格式是:4字节的crc校验码 | 2字节的长度 | 1字节的type | 被分割的数据

 

•type是个枚举值:kFullType,kFirstType,kLastType,kMiddleType。

 

其中:recode的前三部分,组成叫做header,一共占用7个字节,data部分存储数据

我们看一下recode在block中是怎么存储的,这里主要理解,record和block的关系,以及type是怎么用的 

A: 1000字节

1000字节<32768字节
type=kTypeFull

在block1中

 

 

B:87270字节

87270字节>32768字节
type=三个组合使用(first,middle,last)

在block1,2,3中

 

 

C: 8000字节

8000字节<32768字节
type=kTypeFull

 

在block3中


我们再看一下recode在block中详细的存储结构,这里主要理解:record被拆分到多个block中时,是怎么存储的

A 小于 32KB,会被保存到第一个 block,长度为 1000,类型为 kFullType,占用空间为 7 + 1000 = 1007。

B 比较大,会被切分成 3 个分片,保存到不同的 block:

1.第一个分片保存到第一个 block,长度为 31754 字节,类型为 kFirstType。因为保存 A 之后,这个 block 剩余的空间为 32768 - 7 - 1000 = 31761 字节。除去 header,可以保存 B 的前 31761 - 7 = 31754 字节。此时 B 还有 97270 - 31754 = 65516 字节需要保存。

2.65516 字节超过了一个 block 的大小,所以第二个分片需要完整占用第二个 block,长度为 32768 - 7 = 32761 字节,类型为 kMiddleType。此时 B 还有 65516 - 32761 = 32755 字节需要保存。

3.B 的第三个分片保存到第三个 block ,长度为 32755,类型为 kLastType。第三个 block 剩余的空间为 32768 - 7 - 32755 = 6 字节。由于 6 字节小于一个 header 的大小(7 字节),会被进行 padding(填 0)。

C 会被保存到第四个 block,长度为 8000 字节,类型为 kFullType,占用空间 7 + 8000 = 8007。

 

综上,A、B、C 在 log 文件中的结构如图。

 

 

3.3  Immutable Memtable

 

Immutable Memtable 和 Memtable可以理解是一样的结构

 

接下来会讲剩下的三个组件,sstable,manfest,current,请看:
三、levelDB整体框架之sstable,manfest文件,current文件
 

相关内容快速导航:
一、LevelDB设计思想
二、levelDB整体框架,及memtable、log文件、immutable memtable  

三、levelDB整体框架之sstable,manfest文件,current文件

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值