MongoDB 3.2 压力测试
一、测试内容
本次测试目的是衡量MongoDB单机环境的CRUD性能,包括单独及混合CRUD测试。
- C 创建数据,insert操作
- R 读数据,find操作
- U 更新数据,update操作
- D 删除数据,remove操作
二、测试方法及数据准备
本次测试采用开源测试工具Jmeter 3.0进行测试,模拟大用户并发对MongoDB发起请求,达到压力测试的目的。
每单元测试进行5次,观察数据结果的稳定性。
测试数据使用地市结构,city及pop数据为程序随机,模型如下:
1 | { |
三、测试环境
MongoDB服务器:wx-dev-com,2核cpu,4g内存,MongoDB version v3.2.7
Jmeter服务器:wx-dev-test02,2核cpu,4g内存
带宽:金山云内网带宽
MongoDB配置文件:
1 | # mongod.conf |
四、Jmeter设置
测试url:内部链接
Jmeter线程1000,单线程循环200次
测试脚本:内部脚本
参数化文件:内部数据
名词定义(时间的单位均为ms):
Samples – 本次场景中一共完成了多少个线程
Average – 平均响应时间
Median – 统计意义上面的响应时间的中值
90% Line – 所有线程中90%的线程的响应时间都小于xx
Min – 最小响应时间
Max – 最大响应时间
Error – 出错率
Troughput – 吞吐量
KB/sec – 以流量做衡量的吞吐量
五、测试数据
1 插入数据压测
从测试结果看,除了样本1,其他样本的QPS基本在8000以上,可以看到MongoDB的插入能力很不错。
CPU使用率在65%左右,IO操作在压测过后有一些峰值出现,大概是30M/s,应该是批量数据同步到磁盘。
样本 | # Samples | Average | Median | 90% Line | 95% Line | 99% Line | Min | Max | Error % | Throughput | KB/sec |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | 100000 | 4 | 2 | 10 | 18 | 46 | 0 | 348 | 0.00% | 7509.2 | 1078 |
2 | 100000 | 22 | 9 | 69 | 99 | 154 | 0 | 372 | 0.00% | 8058.7 | 1156.9 |
3 | 100000 | 17 | 9 | 47 | 67 | 107 | 0 | 219 | 0.00% | 8392.8 | 1204.8 |
4 | 100000 | 12 | 8 | 31 | 44 | 80 | 0 | 182 | 0.00% | 8332.6 | 1196.2 |
5 | 100000 | 16 | 9 | 45 | 66 | 105 | 0 | 229 | 0.00% | 8530.2 | 1224.6 |
2 查询数据压测
单独查询数据的性能要比插入数据略好,QPS有3次样本突破9200,最低也有8100。
服务器CPU消耗比插入数据低接近50%,
IO写只有插入操作的1/4左右,IOPS只有插入1/10左右,
磁盘读基本没有,可见数据应该是cache在内存了。
每次查询结果集大概是6w数据。
样本 | # Samples | Average | Median | 90% Line | 95% Line | 99% Line | Min | Max | Error % | Throughput | KB/sec |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | 100000 | 1 | 1 | 2 | 3 | 12 | 0 | 83 | 0.00% | 8446.7 | 49.5 |
2 | 100000 | 1 | 1 | 2 | 3 | 15 | 0 | 117 | 0.00% | 8122.8 | 47.6 |
3 | 100000 | 1 | 1 | 2 | 4 | 15 | 0 | 100 | 0.00% | 9398.5 | 55.1 |
4 | 100000 | 1 | 1 | 3 | 5 | 18 | 0 | 142 | 0.00% | 9280.7 | 54.4 |
5 | 100000 | 1 | 1 | 3 | 6 | 22 | 0 | 166 | 0.00% | 9495.8 | 55.6 |
3 更新数据压测
更新数据结果出乎意料的差,Jmeter线程循环降低到10次。
QPS只有100左右,与插入查询比相差几百倍。
IO资源消耗较高,IOPS达到160左右,写操作峰值1500K/s。
怀疑是mongodb的锁机制导致,mongodb只有库级粒度锁。
结果存疑,待验证。
样本 | # Samples | Average | Median | 90% Line | 95% Line | 99% Line | Min | Max | Error % | Throughput | KB/sec |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | 10000 | 8192 | 8754 | 12116 | 12655 | 13525 | 11 | 24492 | 0.00% | 104.9 | 0.3 |
2 | 10000 | 8622 | 9067 | 13659 | 14660 | 16542 | 10 | 29413 | 0.00% | 99.8 | 0.3 |
3 | 10000 | 8173 | 8694 | 12379 | 13082 | 14103 | 8 | 27516 | 0.00% | 104.8 | 0.3 |
4 | 10000 | 8338 | 9054 | 12167 | 12738 | 13570 | 10 | 25689 | 0.00% | 103.5 | 0.3 |
5 | 10000 | 8123 | 8437 | 13196 | 13857 | 15043 | 8 | 29844 | 0.00% | 104.7 | 0.3 |
4 删除数据压测
QPS一路走低,比更新数据性能好一点。
但是使用1000并发进程压测会出现报错,改成并发500进程。
CPU使用率达到了90%以上,已经出现瓶颈了。
IO写峰值有6000KB/s,IOPS 200左右,磁盘压力不高。
样本 | # Samples | Average | Median | 90% Line | 95% Line | 99% Line | Min | Max | Error % | Throughput | KB/sec |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | 5000 | 992 | 828 | 1955 | 2424 | 3258 | 5 | 3625 | 0.00% | 229 | 0.7 |
2 | 5000 | 1326 | 1277 | 2578 | 3277 | 3722 | 10 | 3992 | 0.00% | 212.3 | 0.6 |
3 | 5000 | 1403 | 1264 | 3075 | 3400 | 3723 | 9 | 4085 | 0.00% | 196.1 | 0.6 |
4 | 5000 | 1780 | 1589 | 3521 | 4603 | 5081 | 12 | 5448 | 0.00% | 166.5 | 0.5 |
5 | 5000 | 2179 | 1989 | 4021 | 5410 | 6648 | 19 | 7273 | 0.00% | 146.3 | 0.4 |
5 CRUD混合测试
使用之前单项压测的脚本进行混合压测,Jmeter并发500线程,循环10次。
因为4个操作并发线程一样,从结果看是遵循木桶原理,单项测试QPS是80左右,总体QPS在323左右。
从资源使用率看,瓶颈是CPU,使用率90%,应该是删除数据导致的,与上面单项压测结果一样。
IOPS出现了一个峰值,但是大部分时间磁盘写入不算频繁,平均在1.2MB/s左右。
Label | # Samples | Average | Median | 90% Line | 95% Line | 99% Line | Min | Max | Error % | Throughput | KB/sec |
---|---|---|---|---|---|---|---|---|---|---|---|
Thread Group:Insert | 5000 | 359 | 181 | 1238 | 1417 | 1704 | 0 | 2430 | 0.00% | 81.1 | 11.6 |
Thread Group:Find | 5000 | 323 | 189 | 1072 | 1338 | 1693 | 0 | 2415 | 0.00% | 81.1 | .5 |
Thread Group:Update | 5000 | 2636 | 2578 | 4812 | 5226 | 6168 | 10 | 8164 | 0.00% | 81.2 | .0 |
Thread Group:Remove | 5000 | 1457 | 1387 | 2891 | 3121 | 3953 | 3 | 4488 | 0.00% | 81.1 | .2 |
统计 | 20000 | 1194 | 510 | 3250 | 4163 | 5325 | 0 | 8164 | 0.00% | 323.7 | 12.3 |
六、总结
1.MongoDB强项是数据插入及查询,并发性能非常好,如果压测客户端能多几个的话应该成绩还能提升。
2.对更新及删除数据的成绩不理想,估计和锁机制有关系,有待进一步验证。
3.更新及删除操作超过每秒100次就可以考虑进行分库。
CRUD操作QPS汇总表:
指标 | 插入 | 查询 | 更新 | 删除 | 95% Line | 99% Line | Min | Max | Error % | Throughput | KB/sec |
---|---|---|---|---|---|---|---|---|---|---|---|
CPU | 60% | 40% | 5% | 90% | 1417 | 1704 | 0 | 2430 | 0.00% | 81.1 | 11.6 |
IOPS | 200 | 60 | 170 | 220 | 1338 | 1693 | 0 | 2415 | 0.00% | 81.1 | .5 |
QPS | 8300 | 9000 | 100 | 180 | 5226 | 6168 | 10 | 8164 | 0.00% | 81.2 | .0 |
Thread Group:Remove | 5000 | 1457 | 1387 | 2891 | 3121 | 3953 | 3 | 4488 | 0.00% | 81.1 | .2 |
统计 | 20000 | 1194 | 510 | 3250 | 4163 | 5325 | 0 | 8164 | 0.00% | 323.7 | 12.3 |
附录
压测过程使用的代码
以下代码都是Jmeter的JSR223 sampler使用的代码,并非标准java代码。
插入数据:
1 | import com.mongodb.DB; |
查询数据:
1 | import com.mongodb.DB; |
更新数据:
1 | import com.mongodb.DB; |
删除数据:
1 | import com.mongodb.DB; |