leveldb性能分析和表现
原创文章,转载请注明: 转载自系统技术非业余研究
本文链接地址: leveldb性能分析和表现
Leveldb是一个google实现的非常高效的kv数据库,目前的版本1.2能够支持billion级别的数据量了。 在这个数量级别下还有着非常高的性能,主要归功于它的良好的设计。特别是LSM算法。
那么数据库最怕的的随机IO他是如何解决的呢?
先说随机写,它的写都是先记录到日志文件去的,在日志文件满之前只是简单的更新memtable,那么就把随机写转化成了顺序写。在日志满了后,把日志里面的数据排序写成sst表同时和之前的sst进行合并,这个动作也是顺序读和写。大家都知道传统磁盘raid的顺序读写吞吐量是很大的,100M左右是没有问题。在写日志文件的时候,用到是buffer IO,也就是说如果操作系统有足够的内存,这个读写全部由操作系统缓冲,效果非常好。即使是sync写模式,也是以数据累计到4K为一个单位写的,所以效率高。
那么随机读呢?这个它解决不了。但是ssd盘最擅长随机读了。这个硬件很自然的解决了这个问题。
所以leveldb的绝配是ssd盘的raid.
leveldb标准版本编译见这里,由于标准版本用到了c++ 0x的特性,在RHEL平台下没得到支持,所以为了移植性, basho见这里为它做了标准c++版本的port, 见目录c_src/leveldb. 他之所以用c++ 0x标准主要是用到里面的原子库,basho的port用了libatomicops搞定这个问题.
我们的测试采用的就是这个版本, 我们分别测试了1000万, 1亿,10亿数据量下的leveldb表现,发现随着数据集的变化性能变化不大。
由于leveldb默认的sst文件是2M, 在数据集达到100G的时候要占用几万个文件,我修改了:
version_set.cc:23 static const int kTargetFileSize = 32 * 1048576;
让默认的文件变成32M,减少目录的压力。
我的测试环境是:
$uname -r 2.6.18-164.el5 #RHEL 5U4 # 10* SAS 300G raid卡,fusionIO 320G, Flashcache,内存96G, 24 * Intel(R) Xeon(R) CPU
top说:
21782 root 18 0 1273m 1.1g 2012 R 85.3 1.2 1152:34 db_bench
iostat说:
$iostat -dx 5 ... sdb1 0.40 0.00 3.40 0.00 30.40 0.00 8.94 0.02 4.65 4.65 1.58 fioa 0.00 0.00 2074.80 3.80 16598.40 30.40 8.00 0.00 0.13 0.00 0.00 dm-0 0.00 0.00 1600.00 0.00 16630.40 0.00 10.39 0.25 0.15 0.15 24.76 ...
该测试中请注意snappy压缩没有打开,如果有压缩性能还会高很多,因为IO少了一半。
write_buffer_size=$((256*1024*1024)),log大小设成256M,这样减少切换日志的开销和减少数据合并的频率。
同时应该注意到db_bench是单线程程序,还有一个compact线程,所以最多的时候这个程序只能跑到200%的cpu, IO util也不是很高. 换句话说如果是多线程程序的话性能还要N倍的提高。
我们来看下实际的性能数字:
#1千万条记录 $sudo ./db_bench --num=10000000 --write_buffer_size=$((256*1024*1024)) LevelDB: version 1.2 Date: Fri May 27 17:14:33 2011 CPU: 24 * Intel(R) Xeon(R) CPU X5670 @ 2.93GHz CPUCache: 12288 KB Keys: 16 bytes each Values: 100 bytes each (50 bytes after compression) Entries: 10000000 RawSize: 1106.3 MB (estimated) FileSize: 629.4 MB (estimated) write_buffer_size=268435456 WARNING: Snappy compression is not enabled ------------------------------------------------ fillseq : 2.134 micros/op; 51.8 MB/s fillsync : 70.722 micros/op; 1.6 MB/s (100000 ops) fillrandom : 5.229 micros/op; 21.2 MB/s overwrite : 5.396 micros/op; 20.5 MB/s readrandom : 65.729 micros/op; readrandom : 43.086 micros/op; readseq : 0.882 micros/op; 125.4 MB/s readreverse : 1.200 micros/op; 92.2 MB/s compact : 24599514.008 micros/op; readrandom : 12.663 micros/op; readseq : 0.372 micros/op; 297.4 MB/s readreverse : 0.559 micros/op; 198.0 MB/s fill100K : 349.894 micros/op; 272.6 MB/s (10000 ops) crc32c : 4.759 micros/op; 820.8 MB/s (4K per op) snappycomp : 3.099 micros/op; (snappy failure) snappyuncomp : 2.146 micros/op; (snappy failure) #1亿条记录 $sudo ./db_bench --num=100000000 --write_buffer_size=$((256*1024*1024)) LevelDB: version 1.2 Date: Fri May 27 17:39:19 2011 CPU: 24 * Intel(R) Xeon(R) CPU X5670 @ 2.93GHz CPUCache: 12288 KB Keys: 16 bytes each Values: 100 bytes each (50 bytes after compression) Entries: 100000000 RawSize: 11062.6 MB (estimated) FileSize: 6294.3 MB (estimated) write_buffer_size=268435456 WARNING: Snappy compression is not enabled ------------------------------------------------ fillseq : 2.140 micros/op; 51.7 MB/s fillsync : 70.592 micros/op; 1.6 MB/s (1000000 ops) fillrandom : 6.033 micros/op; 18.3 MB/s overwrite : 7.653 micros/op; 14.5 MB/s readrandom : 44.833 micros/op; readrandom : 43.963 micros/op; readseq : 0.561 micros/op; 197.1 MB/s readreverse : 0.809 micros/op; 136.8 MB/s compact : 123458261.013 micros/op; readrandom : 14.079 micros/op; readseq : 0.378 micros/op; 292.5 MB/s readreverse : 0.567 micros/op; 195.2 MB/s fill100K : 1516.707 micros/op; 62.9 MB/s (100000 ops) crc32c : 4.726 micros/op; 826.6 MB/s (4K per op) snappycomp : 1.907 micros/op; (snappy failure) snappyuncomp : 0.954 micros/op; (snappy failure) #10亿条记录 $sudo ./db_bench --num=1000000000 --write_buffer_size=$((256*1024*1024)) Password: LevelDB: version 1.2 Date: Sun May 29 17:04:14 2011 CPU: 24 * Intel(R) Xeon(R) CPU X5670 @ 2.93GHz CPUCache: 12288 KB Keys: 16 bytes each Values: 100 bytes each (50 bytes after compression) Entries: 1000000000 RawSize: 110626.2 MB (estimated) FileSize: 62942.5 MB (estimated) write_buffer_size=268435456 WARNING: Snappy compression is not enabled ------------------------------------------------ fillseq : 2.126 micros/op; 52.0 MB/s fillsync : 63.644 micros/op; 1.7 MB/s (10000000 ops) fillrandom : 10.267 micros/op; 10.8 MB/s overwrite : 14.339 micros/op; 7.7 MB/s ...比较慢待补充
总结: Leveldb是个很好的kv库,重点解决了随机IO性能不好的问题,多线程更新的性能非常好.
玩得开心!
Post Footer automatically generated by wp-posturl plugin for wordpress.
可以测试一下snappy压缩打开的场景。打开压缩后CPU消耗就高了,性能是否能上去也未必。
Yu Feng Reply:
May 31st, 2011 at 2:12 pm
就看你的IO能力和cpu的关系!
官方还不提供下载.期待快点发展.
Yu Feng Reply:
July 8th, 2011 at 3:44 pm
先研究下,研究明白了,刚好版本也出来了。
在微博上看到有人转你文章前面的那段文字,Google “LSM算法 levelDB”发现很多人转载。
但我对其中 “特别是 LSM 算法” 这句表示不解。我印象中 levelDB的文档没有提到什么 LSM 啊。 wikipedia的 LSM词条(http://en.wikipedia.org/wiki/LSM)里的几种意思,貌似也跟leveldb没关系。
zhpengg Reply:
September 1st, 2011 at 5:26 pm
这里的LSM指的应该是The Log-structured Merge Tree
嵌到MySQL里去~
“在写日志文件的时候,用到是buffer IO,也就是说如果操作系统有足够的内存,这个读写全部由操作系统缓冲,效果非常好。即使是sync写模式,也是以数据累计到4K为一个单位写的,所以效率高。”
sync 写模式不应该有数据累计过程吧,看代码也没有看到此过程。
使用mmap + msync以4K长度为单位sync(每个4K可能重复写)。这种写的方法比 直接 append + fsync 少了更新文件长度的过程,所以效率高?
但文件的修改时间不是也要更新么?所以能比直接 append + fsync 效率高么?
Yu Feng Reply:
February 6th, 2012 at 3:19 pm
同步写模式不是指o_SYNC,那个是写一个刷新一次。 文件的修改时间可以通过关noatime来避免,由于文件是循环使用的,更新文件系统的代价不大。 文件长度是固定,不更新的。用mmap方式要修改写日志的代码,代价大。
一直苦恼levelDB测试中所谓的顺序写是什么样的,请大牛给予指点。
因为测试时可以写入递增的Key,但是进入数据库hash之后hash值就乱了,也就不是顺序写了。
如果时间允许,楼主可否使用email联络,谢谢你的时间。
Yu Feng Reply:
March 27th, 2012 at 8:26 pm
mryufeng@gmail.com
sync 模式时,是每写一条record,都用msync系统调用刷一次盘吧?没有看到到达4k再刷盘啊?求楼主指导
Yu Feng Reply:
June 5th, 2012 at 3:50 pm
我看的是凑4Ksync一次
Beginning Reply:
June 5th, 2012 at 7:25 pm
既然它是sync模式插入,那么就是为了得到更高的可靠性,如果仍然到4k再刷盘,那么数据丢失,仍然恢复不了,从这个角度看,它也不应该设计成到4k在sync 啊?
不能使用java程序访问levelDB 。 很郁闷
Yu Feng Reply:
June 16th, 2012 at 8:52 pm
自己写个封装器
想找一个轻量级的kv db. 选了mongodb,不过它太多nosql的多余功能了,而且占用的各类系统资源太多.
leveldb不错,不过好像不支持multiple replica. 这样的话,数据单点问题怎么办呢?
blackcat Reply:
June 8th, 2013 at 4:04 pm
配合淘宝的tair使用。
博主是否考虑过,调成32兆可能会对随机读性能产生很大影响,因为在一个SST文件中,leveldb是顺序找的,SST越大,顺序找越慢。
ZhangLewis Reply:
July 8th, 2016 at 11:42 am
SST是排序的且除了level0外key都是不重叠的,加上ssd的读性能很好,总的来说性能应该还是不错的
博主说LevelDB配合SSD可以发挥较好的性能,那么LevelDB在SSD上进行compaction的写放大和读性能损耗,是否需要做一个权衡?从SSD的寿命和业务读写比例来考虑