刘浩de技术博客 发表于 2012-12-30 16:39:44

LevelDB Cache实现机制分析

<div id="cnblogs_post_body">   几天前淘宝量子恒道在博客上分析了HBase的Cache机制,本篇文章,结合LevelDB 1.7.0版本的源码,分析下LevelDB的Cache机制。

[*]概述
   LevelDB是Google开源的持久化KV单机存储引擎,据称是HBase的鼻祖Bigtable的重要组件tablet的开源实现。针对存储面对的普遍随机IO问题,LevelDB采用merge-dump的方式,将逻辑场景的随机写请求转换成顺序写log和写memtable的操作,由后台线程根据策略将memtable持久化成分层的sstable。针对读请求,LevelDB会首先查找内存中的memtable和imm(不可变的memtable),然后逐层查找sstable。
   为了加快查找速度,LevelDB在内存中采用Cache的方式,在sstable中采用bloom filter的方式,尽最大可能减少随机读操作。
   LevelDB的Cache分为两种,分别是table cache和block cache。table cache缓存的是sstable的索引数据,类似于文件系统中对inode的缓存;block cache是缓存的block数据,block是sstable文件内组织数据的单位,也是从持久化存储中读取和写入的单位;由于sstable是按照key有序分布的,因此一个block内的数据也是按照key紧邻排布的(有序依照使用者传入的比较函数,默认按照字典序),类似于Linux中的page cache。
   block默认大小为4k,由LevelDB调用open函数时传入的options.block_size参数指定;LevelDB的代码中限制的block最小大小为1k,最大大小为4M。对于频繁做scan操作的应用,可适当调大此参数,对大量小value随机读取的应用,也可尝试调小该参数;
   block cache默认实现是一个8M大小的LRU cache,为了减少锁开销,该LRU cache还分成了16个shard。此参数由options.block_cache设定,即可改变缓存大小,也可根据自己的应用需求,提供新的缓存策略。注意,此处的大小是未压缩的block大小。针对大块文件的读写遍历等需求,为了避免读入的块把之前的热数据都淘汰掉,可以在ReadOptions里设置哪些读取不需要进cache,如以下代码所示:
<div class="cnblogs_code">leveldb::ReadOptions options;options.fill_cache = false;leveldb::Iterator* it = db->NewIterator(options);for (it->SeekToFirst(); it->Valid(); it->Next()) {    ...}
页: [1]
查看完整版本: LevelDB Cache实现机制分析