读了部分LevelDb的code,有以下几点感触:
1. 对资源控制的很小心:Level Db中将内存,文件个数均视作资源,任何一次写入都需要判断当前是否有足够的资源,比如内存是否超过了限定值,文件个数是否已经太多以致持续高速写入将会导致读操作的IO频繁影响性能等;任何一个指标达到了阈值则开始流控,比如每次写入delay 1ms等。
2. 文件compaction的启动标准给出了一个量化指标:
// We arrange to automatically compact this file after // a certain number of seeks. Let's assume: // (1) One seek costs 10ms // (2) Writing or reading 1MB costs 10ms (100MB/s) // (3) A compaction of 1MB does 25MB of IO: // 1MB read from this level // 10-12MB read from next level (boundaries may be misaligned) // 10-12MB written to next level // This implies that 25 seeks cost the same as the compaction // of 1MB of data. I.e., one seek costs approximately the // same as the compaction of 40KB of data. We are a little // conservative and allow approximately one seek for every 16KB // of data before triggering a compaction.
作者认为一次seek大概的cost大概可以相当于compaction 16kb的数据,所以如果一个文件大小是X的话,则seek X/16次的时候其cost已经跟将该文件compaction一样了,这时候就可以启动对该文件的compaction了。
3. 每次访问的时候对memfile ref count ++,这个节省了内存拷贝的开销,但是如果read qps很高的话,可能导致内存中的memtable始终无法被释放,从而可能导致内存占用过多,最后block写,这点不是很有道理。
4. Iterator里面多路merge使用的是简单的数组查找,没有使用优先级队列等,也许作者觉得这个DB就不是为大规模数据访问准备的?
5. 其merge的方法也挺有意思的,将文件分为多个level,除开level0外,其余level中的文件之间没有overlap(http://leveldb.googlecode.com/svn/trunk/doc/impl.html),我觉得这样增加了复杂性,至于性能能好多少就不得而知了。
6. blockindex的key可能未必真正存在,比如两个block的end key分别是i am raymond 和i see youha, 则block index中的key可以存储成i b,因为i b > i am raymond 并且i b < i see youha, 这样降低了blockindex的存储空间。
7. 只要有可能总是使用变长编码和压缩,这个应该是google的强项了
8. block cache里面同时存储了文件信息,当文件被移除的时候,该文件的block也被移除,这个作用个人觉得对性能影响不大,不过如果内存很有限,文件个数以匀速增长和删除,可能是有意义的。
整体感觉,Level DB适合小规模存储,可以当成BerkeleyDB来使用,对于移动开发平台应该挺有优势的,对于构建大规模数据平台可能不合适。
另外感觉LEVELDB的某些实现过于精细,可能google却是碰到了那些我们很少碰到的问题吧。