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性能不好的问题,多线程更新的性能非常好.

玩得开心!

leveldb性能分析的更多相关文章

  1. 如何进行python性能分析?

    在分析python代码性能瓶颈,但又不想修改源代码的时候,ipython shell以及第三方库提供了很多扩展工具,可以不用在代码里面加上统计性能的装饰器,也能很方便直观的分析代码性能.下面以我自己实 ...

  2. SQL Server-聚焦IN VS EXISTS VS JOIN性能分析(十九)

    前言 本节我们开始讲讲这一系列性能比较的终极篇IN VS EXISTS VS JOIN的性能分析,前面系列有人一直在说场景不够,这里我们结合查询索引列.非索引列.查询小表.查询大表来综合分析,简短的内 ...

  3. SQL Server-聚焦NOT IN VS NOT EXISTS VS LEFT JOIN...IS NULL性能分析(十八)

    前言 本节我们来综合比较NOT IN VS NOT EXISTS VS LEFT JOIN...IS NULL的性能,简短的内容,深入的理解,Always to review the basics. ...

  4. SQL Server-聚焦LEFT JOIN...IS NULL AND NOT EXISTS性能分析(十七)

    前言 本节我们来分析LEFT JOIN和NOT EXISTS,简短的内容,深入的理解,Always to review the basics. LEFT JOIN...IS NULL和NOT EXIS ...

  5. SQL Server-聚焦EXISTS AND IN性能分析(十六)

    前言 前面我们学习了NOT EXISTS和NOT IN的比较,当然少不了EXISTS和IN的比较,所以本节我们来学习EXISTS和IN的比较,简短的内容,深入的理解,Always to review ...

  6. SQL Server-聚焦NOT EXISTS AND NOT IN性能分析(十五)

    前言 上一节我们分析了INNER JOIN和IN,对于不同场景其性能是不一样的,本节我们接着分析NOT EXISTS和NOT IN,简短的内容,深入的理解,Always to review the b ...

  7. SQL Server-聚焦INNER JOIN AND IN性能分析(十四)

    前言 本节我们来讲讲联接综合知识,我们在大多教程或理论书上都在讲用哪好,哪个性能不如哪个的性能,但是真正讲到问题的实质却不是太多,所以才有了本系列每一篇的篇幅不是太多,但是肯定是我用心去查找许多资料而 ...

  8. Java 性能分析工具 , 第 3 部分: Java Mission Control

    引言 本文为 Java 性能分析工具系列文章第三篇,这里将介绍如何使用 Java 任务控制器 Java Mission Control 深入分析 Java 应用程序的性能,为程序开发人员在使用 Jav ...

  9. Java 性能分析工具 , 第 2 部分:Java 内置监控工具

    引言 本文为 Java 性能分析工具系列文章第二篇,第一篇:操作系统工具.在本文中将介绍如何使用 Java 内置监控工具更加深入的了解 Java 应用程序和 JVM 本身.在 JDK 中有许多内置的工 ...

随机推荐

  1. 二、oracle sql*plus常用命令

    一.sys用户和system用户Oracle安装会自动的生成sys用户和system用户(1).sys用户是超级用户,具有最高权限,具有sysdba角色,有create database的权限,该用户 ...

  2. Ext 下拉框联动第一次显示不正常的问题

    做下拉框联动,异步加载数据,第一次显示时数据不准确,不要在combo_2的下拉框直接绑定store,在combo_1的改变事件里调用下面的方法 function GetAllCustomerBrand ...

  3. php给数组key:value中的key加引号

    public function Ext_json_decode($str, $mode=false){ if(preg_match('/\w:/', $str)){ $str = preg_repla ...

  4. MYSQL超时连接问题(com.mysql.jdbc.MysqlIO.readFully)

    应用服务器连接mysql,有时候会出现以下异常: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.jav ...

  5. 第三十六节,os系统级别操作模块

    在使用os模块时需要先 import os 引入模块 os.getcwd()模块函数 功能:获取当前工作目录,即当前python脚本工作的目录路径[无参] 使用方法:os.getcwd() 格式如:a ...

  6. Linq第二讲

    这一讲,来说说集合.因为linq主要用于对数据源进行查询,集合是最常见的数据源. 集合 形式: 数组,列表List<T> Arraylist等. 特点: 可通过索引或键访问.可进行fore ...

  7. svn revert

    本地开发环境出现一个问题,用revert完美解决. 问题描述: 文件static/image/common/jiqiaodaren.png已经被提交到svn上,但是我的开发环境因未与svn同步,所以没 ...

  8. vs2013执行Add-Migration出现的问题

    1. 无法将"Add-Migration"项识别为 cmdlet.函数.脚本文件或可运行程序的名称.请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次 网上解决方法为:h ...

  9. Inno Setup入门(二十)——Inno Setup类参考(6)

    存储框 存储框也是典型的窗口可视化组件,同编辑框类似,可以输入.显示文本,但是和编辑框不同的是,编辑框只能编辑.显示单行文本,而存储框则可以对多行文本进行操作.存储框的类定义如下:< xmlna ...

  10. redis配置密码认证

    redis配置密码 1.通过配置文件进行配置yum方式安装的redis配置文件通常在/etc/redis.conf中,打开配置文件找到 ? 1 #requirepass foobared 去掉行前的注 ...