LevelDB是google开发的、高效的键值存储程序库。之所以称之为程序库而非代码库是因为它仅仅是一个library文件,无法单独运行,宿主为leveldb使用者。
1.1 特性
- key、value可以是任意的byte数组
- 数据按key排序后存储
- 使用者可提供自定义比较器以决定key的排序方式
- 基本操作包括Put(key,value), Get(key), Delete(key)
- 支持原子的批量修改操作
- 支持创建快照(用后需及时释放),获取当前的一致性数据
- 数据支持向前、向后的迭代器
- 数据自动压缩,采用 Snappy compression library.
- 外部依赖(文件系统操作等)通过接口完成,用户可定制实现。
1.2 限制
- LevelDB不是SQL数据库,不支持关系数据模型,不支持SQL查询,也不支持创建索引。
- 同时只能有一个进程(允许多线程)访问数据库。
- 不支持client-server模式,使用者可以基于该library构建自己的服务器。
1.3 性能
下面的性能测试报告基于db_bench程序,结果存在一定干扰,但做为性能评估是足够的。
1.3.1 验证场景
我们使用一个数百万记录的数据库,每条记录的key大小为16字节,value大小为100字节。基准测试的Value大小压缩为原始大小的一半。
LevelDB: version 1.1
Date: Sun May 1 12:11:26 2011
CPU: 4 x Intel(R) Core(TM)2 Quad CPU Q6600 @ 2.40GHz
CPUCache: 4096 KB
Keys: 16 bytes each
Values: 100 bytes each (50 bytes after compression)
Entries: 1000000
Raw Size: 110.6 MB (estimated)
File Size: 62.9 MB (estimated)
1.3.2 写性能
“填充”基准测试以顺序或随机顺序创建一个全新的数据库。 每次操作后,“fillsync”基准将数据从操作系统刷新到磁盘(顺序操作); 其他写入操作则利用操作系统缓冲区高速缓存中一段时间。 “覆盖”基准做随机写入,更新数据库中的现有key值记录。
fillseq : 1.765 micros/op; 62.7 MB/s; 56.6W+ OP/S
fillsync : 268.409 micros/op; 0.4 MB/s (10000 ops); 0.37W OP/S
fillrandom : 2.460 micros/op; 45.0 MB/s; 40W+ OP/S
overwrite : 2.380 micros/op; 46.5 MB/s; 42W+ OP/S
"op"是指一次写入一个key/value对。随机写性能大约在40W op/s,“fillsync”操作时间(0.3 millisecond)甚至少于磁盘seek时间(典型时间为10millisecond)。我们怀疑这可能是因为硬盘自身存在缓存(memory),并在数据真正落盘前进行响应。这样做是否安全取决于出现电力故障时,是否来得及将缓存中的数据写入磁盘。
1.3.3 读性能
我们列出了正向和反向方向上顺序读取的性能,以及随机查找的性能。 请注意,基准数据库创建的数据库相当小, 报告中的leveldb性能数据基本是基于内存操作的。 读取操作系统高速缓冲区中不存在的数据时,将额外执行1-2次磁盘查找动作。 写性能基本不受数据是否在内存中的影响。
readrandom : 16.677 micros/op; (approximately 60,000 reads per second)
readseq : 0.476 micros/op; 232.3 MB/s; 210W+ op/s
readreverse : 0.724 micros/op; 152.9 MB/s; 138W+ op/s
LevelDB在后台压缩其底层存储数据,以提高读取性能。 上面列出的结果是在大量随机写作之后立即进行的。 压缩后的结果(通常自动触发)更好。
readrandom : 11.602 micros/op; (approximately 85,000 reads per second)
readseq : 0.423 micros/op; 261.8 MB/s; 236W+ op/s
readreverse : 0.663 micros/op; 166.9 MB/s; 150W+ op/s
其中,某些读操作由于重复读取磁盘并解压缩以致耗时较长。我们为leveldb提供足够的缓存,以便可以将未压缩的块保存在内存中,则读取性能再次提高:
readrandom : 9.775 micros/op; (approximately 100,000 reads per second before compaction)
readrandom : 5.215 micros/op; (approximately 190,000 reads per second after compaction)
对于典型的数据库操作,基本为随机读、写,整理下上述关键性能数据:
fillrandom : 2.460 micros/op; 45.0 MB/s; 40W+ OP/S
readrandom : 9.775 micros/op; (approximately 100,000 reads per second before compaction)
readrandom : 5.215 micros/op; (approximately 190,000 reads per second after compaction)
随机写的性能大致为40W+ op/s,读在数据压缩完成后性能最佳为19W+ op/s,运行时的实时读性能大约为10W+ op/s。
1.4 总结
leveldb是一个键值数据库,app嵌入该程序库后可完成基于key的读、写操作,其写操作性能极佳,甚至远高于读性能。
leveldb总代码9.6k,其中还包含了大量的测试程序,做为一个小巧的,功能完备的键值数据库,非常具有研究价值。
leveldb内部并未使用MVCC,而是使用了一种古老的LSM数据结构。除此之外,还使用了skiplist简化处理逻辑,创建定制的内存池提高程序性能,精巧的分层布局等等。
本系列文章将剖析leveldb设计、实现的各个细节,对其支持的各种特性、特别是性能优化上做详细分析。
本文基于leveldb 1.2版本分析。
注:本节大部分内容来自leveldb git主页(https://github.com/google/leveldb)。
转载请注明:[随安居士]http://www.jianshu.com/p/9b5945cb6e70