leveldb研究系列二——各个组件和读写时序介绍

来源:互联网 发布:js获取li标签的属性值 编辑:程序博客网 时间:2024/06/07 01:52

在学习leveldb的过程中,我走了很多弯路,比如在对整体了解不足的情况下就开始阅读源代码,这其实是不可取的,所以我希望大家在学习leveldb的时候要对整体有个大致的了解,这样就可以加快整个学习过程,leveldb涉及很多数据结构的知识( skiplist,  bloom filter, 多路归并排序,还有一个LRUcache,hash,等等) 还有一点点令人棘手底层的问题,多线程,并发控制,原子操作,内存屏障,(memory barrier,想想关键字volitale)编码约定(大小端)。

总而言之,希望大家先有相关准备再去看源代码,让我先给大家介绍leveldb的组件和读写时序:

1.首先 我们要牢记,leveldb的是一个用来提高写性能的,内存小巧可控的KV数据库(可控的原因是在于后面讲到cache可以配置,可选), 采用一系列的方式保证写性能  先上图 给个写时序



write 操作很简单,写入磁盘log (顺序写入数据),在memtable 插入<key,value>  ,memtalbe主要依靠skiplist实现数据挂载,skiplist是一种类似于自平衡二叉树的数据结构,不过相对而言具有更好的写性能(调整节点少)   在后续章节我会详细讲解此数据结构。      到这里为止, write操作已经结束,也就是说write操作包括一次顺序磁盘顺序写,一次写内存。(现在应该有感觉,leveldb为何写这么快)  这里还有一个immutable memtable,  是这样的,在memtable达到check point(要满员的时候) memtable 就成immutable memtable(同时会有新的log被启用) 顾名思义,是不变的,只读不写,等待线程写入磁盘,生成SSTable文件(SSTable0)  SSTable会compaction到下N层, 一层又一层,所以叫leveldb.....  

顺便说一下,删除,修改都是write操作,删除只是做标记,修改是插入和原来key一样的新值,这些操作本质上都是写, 最后的物理的上删除和修改要到SSTbale合并的时候才执行 ,lazzy done,这里用到了Sequence来指明操作先后次序,在合并的时候保证取用最新的值,后续详讲。(谁能告诉我,这个编辑器怎么用?复制一个单词就变了字体,无力吐槽。。。。)

接下来该说说读时序,读是非常复杂和曲折,先上个图,ps :visio太渣 画了老半天(/ □ \)



虽然数据并没有即时的被归档,但是 数据有先后次序,按照先后次序,我们先在内存的memtable 和 immutable memtable 查找,如果没有找到我们就要去磁盘下面找或者在cache中,  这里有mainfest索引文件,指出SSTable 中开始和结束key 的区间,据此可以定位,key可能在哪个sstable中,需要提到sstble0 和其他sstbale区间是有可能重叠,其他sstbale区间彼此不重叠,这句话的意思就是说manifest查阅的结果,要么指定一个可能的sstbale;  要么有两个,并且一个是sstbale 0。

mainfest指出可能的sstable,  如果系统配置了cache被选用,这时候会首先在cache中查找,否则把磁盘中的sstbale调入内存cache中, 每个sstbale都有自己索引文件用来快速(按照磁盘block索引)在查找索引之前,首先采取bloom filter过滤大部分不在其中的数据,而后在查找索引,找到数据block,最后才能返回。   真的好曲折啊。。。。哈哈

 到此为止,我已经简单介绍了leveldb的读写时序,和各个组件功能,不过sstable的归并还没介绍,下章详细将,上次提到的lsm_tree策略,这里简单说来就是 不要即刻更新索引,而等到某个点,批量处理,合并排序, 这样写就会很快(不需要合并更新)  带来的副作用并不大,   这里副作用体现在 在读 查阅的时候,要先查找内存数据,再查找磁盘中归并的数据,而不是一次可以查找一个索引。  这样做的目的就是为了加快读,并且由于批量处理索引会大大减少磁盘I/O 。关于lsm_tree策略详见http://blog.csdn.net/v_july_v/article/details/7526689  (这人是我本科校友 哈哈哈哈)

哈哈    下面的章节我会详细介绍,各个组件组成,关键数据结构,源代码接口,性能比较      等等   未完待续。。。

0 0
原创粉丝点击