您当前的位置:首页 > mongodb

使用YCSB测试MongoDB的微分片性能

MongoDB的库级锁ZhRlinux系统宝典

MongoDB是目前最流行的NoSQL数据库,以其自然的文档型数据结构,灵活的数据模式以及简单易用的水平扩展能力而获得了很多开发人员的青睐。 但是金无足赤人无完人,MongoDB不是没有它的一些弱点,比如说它的库级锁就是人们经常抱怨的一个性能瓶颈。简单来说MongoDB的库级锁就是针对某一个数据库的所有写操作,必须在获得这个数据库仅有的一个互斥锁情况下才能进行。这个听上去很糟糕,但实际上由于一个写操作只是针对于内存数据更新的那一刹那保留锁,所以每个写锁的占用时间通常是在纳秒级别。正因为如此,实际应用中库级锁并没有对性能产生人们所担忧的那样显著的影响。ZhRlinux系统宝典

在少数超高并发写的应用场景下,库级锁会可能是一个瓶颈。这个可以通过MongoDB的MMS监控里面的DB Lock %(或者mongostat的命令行输出)指标来进行观察。一般情况下如果DB Lock %超过70-80%并持续就可以认为已经到饱和状态了。如何解决这个问题呢?ZhRlinux系统宝典

方案一: 分片ZhRlinux系统宝典
这个是MongoDB的标准答案如果你有足够的硬件资源。 分片是解决大部分性能瓶颈问题的终极方式。ZhRlinux系统宝典

方案二:分库ZhRlinux系统宝典
这是个非常有效的变通手段。具体做法就是把你的数据分到几个不同的数据库里,然后在应用程序里的数据访问层实现一个路由切换,保证数据读写会被指向到相应的数据库里。一个比较好的例子在一个人口普查的数据库里,你可以为每个省建一个单独的库。31个数据库组成一个逻辑大库。但是这种做法不是什么时候都能用的,比如说如果你需要很多整库数据的查询排序那样的操作,那么协调多个库的结果就会显得很麻烦或者无法实现。ZhRlinux系统宝典

方案三:等待ZhRlinux系统宝典
MongoDB 2.8 即将发布。2.8的最大改动就是把库级锁改成了文档级锁。由库级锁引起的性能问题应该有望得到较大改善。ZhRlinux系统宝典

方案四:微分片ZhRlinux系统宝典
微分片的定义就是使用MongoDB的分片技术,但是多个或者全部分片Mongod运行在同一台服务器(服务器可以是物理机或者虚机)上。由于库级锁的存在,以及MongoDB对多核CPU的利用率不是很高的特性,微分片在满足以下条件的场景下会是一个不错的性能调优手段:  ZhRlinux系统宝典
1) 服务器有多核(4或8或更多)CPU    ZhRlinux系统宝典
2) 服务器尚未出现IO瓶颈    ZhRlinux系统宝典
3) 有足够内存装下热数据(没有出现频繁的 page faults)ZhRlinux系统宝典

在这篇文章里我们通过做一些性能测试来看一下使用微分片技术以后对性能提升的影响。ZhRlinux系统宝典

YCSB 性能测试工具ZhRlinux系统宝典

在开始测试之前,我想首先花点时间介绍一下YCSB这个工具。原因是很多时候我看到开发工程师或者DBA们做测试的时候往往会用一些非常简单的工具作为客户端进行高并发的插入或读取测试。MongoDB本身是一个高性能的数据库,并发量在适当调优的情况下可以达到每秒数万级。如果客户端的代码是简单粗暴型的,甚至使用单线程的客户端,那么性能测试的瓶颈首先就是在客户端本身,而不是服务器。所以选择一个高效的客户端是一个好的性能测试的重要的第一步。ZhRlinux系统宝典

YCSB是Yahoo开发的一个专门用来对新一代数据库进行基准测试的工具。全名是Yahoo! Cloud Serving Benchmark。 他们开发这个工具的目的是希望有一个标准的工具用来衡量不同数据库的性能。YCSB做了很多优化来提高客户端性能,例如在数据类型上用了最原始的比特数组以减少数据对象本身创建转换所需的时间等。YCSB的几大特性:ZhRlinux系统宝典
* 支持常见的数据库读写操作,如插入,修改,删除及读取  ZhRlinux系统宝典
* 多线程支持。YCSB用Java实现,有很好的多线程支持。ZhRlinux系统宝典
* 灵活定义场景文件。可以通过参数灵活的指定测试场景,如100%插入, 50%读50%写等等  ZhRlinux系统宝典
* 数据请求分布方式:支持随机,zipfian(只有小部分的数据得到大部分的访问请求)以及最新数据几种请求分布方式    ZhRlinux系统宝典
* 可扩展性:可以通过扩展Workload的方式来修改或者扩展YCSB的功能ZhRlinux系统宝典

安装YCSBZhRlinux系统宝典

由于YCSB本身会承担很大的工作量,一般建议部署YCSB在单独的机器上,最好是4-8核CPU,8G内存以上。YCSB和数据库服务器最少要保证千兆的带宽,最好是万兆级。ZhRlinux系统宝典
* 安装JDK 1.7  ZhRlinux系统宝典
* 下载实现了MongoDB驱动的YCSB编译版:ZhRlinux系统宝典

资源包下载地址ZhRlinux系统宝典

------------------------------------------分割线------------------------------------------ZhRlinux系统宝典

FTP地址:ZhRlinux系统宝典

用户名:ftp1.linuxidc.comZhRlinux系统宝典

密码:www.linuxidc.comZhRlinux系统宝典

在 2015年LinuxIDC.com/7月/使用YCSB测试MongoDB的微分片性能ZhRlinux系统宝典

下载方法见 ZhRlinux系统宝典

------------------------------------------分割线------------------------------------------ZhRlinux系统宝典

* 解压缩    ZhRlinux系统宝典
* 进入到ycsb目录并运行(本地要有一个Mongo数据库在 27017端口上):    ZhRlinux系统宝典
./bin/ycsb run mongodb -P workloads/workloadaZhRlinux系统宝典
* 如果YCSB可以运行则表明安装成功ZhRlinux系统宝典
你也可以用Git把源文件拉下来自己编译。需要JDK和Maven工具。Github地址是: 可以参考这个页面进行编译安装YCSB: ZhRlinux系统宝典

YCSB场景文件ZhRlinux系统宝典

使用YCSB测试不同场景只需要提供不同的场景文件就可以。YCSB会按照你的场景文件的属性而自动生成响应的客户端请求。在我们这次测试里我们会使用到几种场景:ZhRlinux系统宝典
场景S1: 100%插入。用来加载测试数据  ZhRlinux系统宝典
场景S2: 写多读少 90% 更新 10%读    ZhRlinux系统宝典
场景S3: 混合读写 65%读, 25% 插入, 10% 更新    ZhRlinux系统宝典
场景S4: 读多写少 90% 读, 10% 插入、更新    ZhRlinux系统宝典
场景S5: 100%读ZhRlinux系统宝典

如下是其中场景文件S2的内容:ZhRlinux系统宝典
recordcount=5000000  ZhRlinux系统宝典
operationcount=100000000    ZhRlinux系统宝典
workload=com.yahoo.ycsb.workloads.CoreWorkloadZhRlinux系统宝典
readallfields=trueZhRlinux系统宝典
readproportion=0.1  ZhRlinux系统宝典
updateproportion=0.9    ZhRlinux系统宝典
scanproportion=0    ZhRlinux系统宝典
insertproportion=0ZhRlinux系统宝典
requestdistribution=uniformZhRlinux系统宝典
insertorder=hashedZhRlinux系统宝典
fieldlength=250  ZhRlinux系统宝典
fieldcount=8ZhRlinux系统宝典
mongodb.url=mongodb://192.168.1.2:27017  ZhRlinux系统宝典
mongodb.writeConcern=acknowledged    ZhRlinux系统宝典
threadcount=32ZhRlinux系统宝典

一些说明:ZhRlinux系统宝典
* 测试数据包括500万个文档(recordcount)  ZhRlinux系统宝典
* 每个文档大小大约2KB(fieldlength x fieldcount)。数据总共大小是10G+600M的索引    ZhRlinux系统宝典
* MongoDB数据库的url是192.168.1.2:27017    ZhRlinux系统宝典
* MongoDB的写安全设置(mongodb.writeConcern)是acknowledged    ZhRlinux系统宝典
* 线程数是32(threadcount)    ZhRlinux系统宝典
* 插入文档的顺序:哈希/随机 (insertorder)    ZhRlinux系统宝典
* 更新操作: 90% (0.9)    ZhRlinux系统宝典
* 读操作: 10% (0.1)ZhRlinux系统宝典

下载所有场景文件(S1 – S5)(见上面的Linux公社下载地址) 并解压到上面创建的ycsb目录下面:ZhRlinux系统宝典

MongoDB配置ZhRlinux系统宝典

本次测试是在AWS的虚拟主机上进行测试的。以下是服务器配置情况:ZhRlinux系统宝典
* OS: Amazon Linux (和基本类似)  ZhRlinux系统宝典
* CPU: 8 vCPU    ZhRlinux系统宝典
* RAM: 30G    ZhRlinux系统宝典
* Storage: 160G SSD    ZhRlinux系统宝典
* Journal: 25G EBS with 1000 PIOPS    ZhRlinux系统宝典
* Log: 10G EBS with 250 IOPS    ZhRlinux系统宝典
*    ZhRlinux系统宝典
* MongoDB: 2.6.0    ZhRlinux系统宝典
* Readahead:32ZhRlinux系统宝典

几点说明:  ZhRlinux系统宝典
MongoDB的数据,恢复日志(journal)以及系统日志(log)分别用了3个不同的存储盘。这是一个常见的优化方式,以保证写日志的操作不会影响到数据的刷盘IO。另外服务器的readahead设置改到了推荐的32。关于readahead等可以参见: ZhRlinux系统宝典

单机基准测试ZhRlinux系统宝典

在我们测试使用微分片性能之前我们首先需要得出单机的最高性能。启动目标MongoDB服务器,登录上去后先删除ycsb数据库(如果已经存在)ZhRlinux系统宝典
# mongo ZhRlinux系统宝典
> use ycsb    ZhRlinux系统宝典
> db.dropDatabase()ZhRlinux系统宝典

场景S1: 数据插入ZhRlinux系统宝典
接下来开始运行YCSB。进到ycsb目录下,运行以下命令(确认当前目录下已经有场景文件S1, S2, S3, S4,S5)ZhRlinux系统宝典
./bin/ycsb load mongodb -P S1 -sZhRlinux系统宝典

如果运行正常,你会看到每隔10秒YCSB打印一下当前状态,包括每秒的并发率以及平均响应时间。 如:ZhRlinux系统宝典
Loading workload…  ZhRlinux系统宝典
Starting test.    ZhRlinux系统宝典
0 sec: 0 operations;    ZhRlinux系统宝典
mongo connection created with localhost:27017/ycsb    ZhRlinux系统宝典
10 sec: 67169 operations; 7002.16 current ops/sec; [INSERT AverageLatency(us)=4546.87]    ZhRlinux系统宝典
20 sec: 151295 operations; 7909.24 current ops/sec; [INSERT AverageLatency(us)=3920.9]    ZhRlinux系统宝典
30 sec: 223663 operations; 7235.35 current ops/sec; [INSERT AverageLatency(us)=4422.63]ZhRlinux系统宝典

在运行的同时你可以用mongostat(或者更好的选择:MMS)来监控MongoDB的实时指标,看是否和YCSB的报告大体一致。ZhRlinux系统宝典

运行结束后可以看到类似于如下输出:ZhRlinux系统宝典
[OVERALL], RunTime(ms), 687134.0  ZhRlinux系统宝典
[OVERALL], Throughput(ops/sec), 7295.168457372555    ZhRlinux系统宝典
…    ZhRlinux系统宝典
[INSERT], Operations, 5000000    ZhRlinux系统宝典
[INSERT], AverageLatency(us), 4509.1105768    ZhRlinux系统宝典
[INSERT], MinLatency(us), 126    ZhRlinux系统宝典
[INSERT], MaxLatency(us), 3738063    ZhRlinux系统宝典
[INSERT], 95thPercentileLatency(ms), 10    ZhRlinux系统宝典
[INSERT], 99thPercentileLatency(ms), 37    ZhRlinux系统宝典
[INSERT], Return=0, 5000000    ZhRlinux系统宝典
ZhRlinux系统宝典

这个输出告诉我们插入了500万条记录, 耗时687秒,平均并发量每秒7295条,平均响应时间4.5ms。注意这个数值本身来说对于MongoDB的性能指标没有任何参考价值。如果你的环境有任意一点不一致,或者插入数据的大小,或者索引的多少不一样,都会导致结果很大的不同。所以这个值只能在作为本次测试和微分片性能比较的基准值。ZhRlinux系统宝典

在MongoDB方面,要特别注意一下mongostat或者MMS汇报的page faults,network,DB Lock %等指标。如果你的network是1Gb/s 而mongostat汇报了100m的数字,那你的网络就基本是饱和了。1Gb/s的带宽也就是128m/s的传输速率。在我的这个测试里network in保持在14-15m/s的样子,和每秒的并发率及文档大小(7300x2KB)是一致的。ZhRlinux系统宝典

为了找到一个比较理想的客户端线程数,我对同样的操作重复了多次,每一次修改了场景文件里面的threadcount数值。测试的结果发现到了30 个线程左右并发量就到达了最高值。再增加线程数量性能不再提高。因为我的场景文件中的threadcount值设为32。ZhRlinux系统宝典

现在我们已经在数据库内有了500万测试数据,现在我们可以测一下其他的几个场景。注意:YCSB的第一个参数是测试阶段。刚才是数据导入所以第一个参数是”load”。导入完数据后接下来就是运行阶段所以第二个参数都是”run”。ZhRlinux系统宝典

场景S2: 写多读少ZhRlinux系统宝典
命令:ZhRlinux系统宝典
./bin/ycsb run mongodb -P S2 -sZhRlinux系统宝典
结果  ZhRlinux系统宝典
…    ZhRlinux系统宝典
[OVERALL], Throughput(ops/sec), 12102.2928384723ZhRlinux系统宝典

场景S3: 混合读写(65%read)ZhRlinux系统宝典
命令:ZhRlinux系统宝典
./bin/ycsb run mongodb -P S3 -sZhRlinux系统宝典
结果  ZhRlinux系统宝典
…    ZhRlinux系统宝典
[OVERALL], Throughput(ops/sec), 15982.39239483840ZhRlinux系统宝典

场景S4: 读多写少ZhRlinux系统宝典
命令:ZhRlinux系统宝典
./bin/ycsb run mongodb -P S4 -sZhRlinux系统宝典
结果  ZhRlinux系统宝典
…    ZhRlinux系统宝典
[OVERALL], Throughput(ops/sec), 19102.39099223948ZhRlinux系统宝典

场景S5: 100% 读ZhRlinux系统宝典
命令:ZhRlinux系统宝典
./bin/ycsb run mongodb -P S5 -sZhRlinux系统宝典
结果  ZhRlinux系统宝典
…    ZhRlinux系统宝典
[OVERALL], Throughput(ops/sec), 49020.29394020022ZhRlinux系统宝典

微分片测试ZhRlinux系统宝典

刚才我们已经得到了单机在5个场景下的性能指标。接下来我们可以开始测试在微分片以及不同数量微分片的情景下的性能指标。ZhRlinux系统宝典

首先我们停掉单机上MongoDB数据库。ZhRlinux系统宝典
接下来我们要建一个分片集群。在这里让我要推荐给大家一个非常方便的MongoDB工具:mtools   ZhRlinux系统宝典

mtools是几个MongoDB相关工具的集合,其中的mlaunch可以帮助我们不费吹灰之力地在单机上创建复制集或分片集群。ZhRlinux系统宝典

安装mtools(需要Python以及Python的包管理工具pip 或者easy_install):ZhRlinux系统宝典
# pip install mtoolsZhRlinux系统宝典

ZhRlinux系统宝典

# easy_install mtoolsZhRlinux系统宝典

然后建一个新的目录并在新目录下创建微分片集群:ZhRlinux系统宝典
# mkdir shard2    ZhRlinux系统宝典
# cd shard2    ZhRlinux系统宝典
# mlaunch –sharded 2 –singleZhRlinux系统宝典

这个命令会在同一台机器上创建一下4个进程:ZhRlinux系统宝典
* 1 个mongos 在27017 端口  ZhRlinux系统宝典
* 1 个配置服务器的mongod 在27020端口    ZhRlinux系统宝典
* 2 个分片服务器的mongod 在27018和27019端口ZhRlinux系统宝典

这四个进程组成了具有两个分片的微分片集群。值得指出的是虽然我们已经搭建了一个分片集群,在这个时候所有的数据还是只会去到其中一个分片,这个分片叫做主分片。要让MongoDB把数据分布到各个分片上,必须显式地激活需要分片的数据库以及集合名。ZhRlinux系统宝典
# mongo    ZhRlinux系统宝典
mongos> sh.enableSharding(“ycsb”)    ZhRlinux系统宝典
{ “ok” : 1 }    ZhRlinux系统宝典
mongos> sh.shardCollection(“ycsb.usertable”, {_id:”hashed”})    ZhRlinux系统宝典
{ “collectionsharded” : “ycsb.usertable”, “ok” : 1 }ZhRlinux系统宝典

上述两个命令分别激活了 ”ycsb“ 数据库以及库内 “usertable”集合的分片功能。在对集合开启分片的时候还需要指定分片键。在这里我们使用了 {_id: “hashed” } 表示使用 _id 字段的哈希值作为分片键。哈希值分片键对大量写的场景比较合适,可以把写操作均匀的分布到各个分片上。ZhRlinux系统宝典

接下来我们可以按顺序运行以下5个场景并收集测试结果(注意ycsb的第一个参数):ZhRlinux系统宝典
./bin/ycsb load mongodb -P S1 -s    ZhRlinux系统宝典
./bin/ycsb run mongodb -P S2 -s    ZhRlinux系统宝典
./bin/ycsb run mongodb -P S3 -s    ZhRlinux系统宝典
./bin/ycsb run mongodb -P S4 -s    ZhRlinux系统宝典
./bin/ycsb run mongodb -P S5 -sZhRlinux系统宝典

测试完以后要用下述命令关掉整个集群:ZhRlinux系统宝典
# mlaunch stopZhRlinux系统宝典

以次类推,可以对4个,6个,和8个成员的微分片集群分别建立单独的目录并重复5个场景的测试。如下是所有测试结果:ZhRlinux系统宝典

ZhRlinux系统宝典

ZhRlinux系统宝典

ZhRlinux系统宝典

结论ZhRlinux系统宝典

从上表我们可以得出以下结论ZhRlinux系统宝典

* 微分片在合适的应用场景下可以显著的提高MongoDB并发量  ZhRlinux系统宝典

* 微分片对只读的应用场景没有任何帮助   ZhRlinux系统宝典

* 微分片对混合读写的场景(也是实际中最常见的场景)的优化最好:275%   ZhRlinux系统宝典

* 6个微分片就已经基本到了饱和状态,再增加更多分片已经没有明显改善。 这个数字可能会因人而异。ZhRlinux系统宝典

MongoDB 3.0 正式版发布下载  ZhRlinux系统宝典

CentOS编译安装MongoDB ZhRlinux系统宝典

CentOS 编译安装 MongoDB与mongoDB的php扩展 ZhRlinux系统宝典

CentOS 6 使用 yum 安装MongoDB及服务器端配置 ZhRlinux系统宝典

13.04下安装MongoDB2.4.3 ZhRlinux系统宝典

MongoDB入门必读(概念与实战并重) ZhRlinux系统宝典

Ubunu 14.04下MongoDB的安装指南 ZhRlinux系统宝典

《MongoDB 权威指南》(MongoDB: The Definitive Guide)英文文字版[PDF] ZhRlinux系统宝典

Nagios监控MongoDB分片集群服务实战 ZhRlinux系统宝典

基于CentOS 6.5操作系统搭建MongoDB服务 ZhRlinux系统宝典

MongoDB 的详细介绍ZhRlinux系统宝典
MongoDB 的下载地址ZhRlinux系统宝典



沪ICP备10206494号-4