Luc*_*iva 7 concurrency mongodb
问题是关于我在MongoDB上遇到的并发瓶颈.如果我进行一次查询,则需要1个单位的时间才能返回; 如果我进行2个并发查询,则需要2个单位的时间才能返回; 通常,如果我进行n个并发查询,则所有这些查询都需要n个单位才能返回.我的问题是在面对并发查询时可以采取哪些措施来改善Mongo的响应时间.
我在AWS上有一个运行MongoDB 2.6.7服务器的m3.medium实例.m3.medium有1个vCPU(Xeon E5-2670 v2的1个核心),3.75GB和4GB SSD.
我有一个名为的单个集合的数据库user_products.此集合中的文档具有以下结构:
{ user: <int>, product: <int> }
Run Code Online (Sandbox Code Playgroud)
有1000个用户和1000个产品,每个用户 - 产品对都有一个文档,总计一百万个文档.
该集合有一个索引{ user: 1, product: 1 },我的结果都是indexOnly.
测试是在运行MongoDB的同一台机器上执行的.我正在使用benchRunMongo提供的功能.在测试期间,没有对MongoDB进行其他访问,并且测试仅包含读取操作.
对于每个测试,模拟了许多并发客户端,每个客户端都会尽可能多地进行一次查询,直到测试结束.每次测试运行10秒.并发性以2的幂来测试,从1到128个并发客户端.
运行测试的命令:
mongo bench.js
Run Code Online (Sandbox Code Playgroud)
这是完整的脚本(bench.js):
var
seconds = 10,
limit = 1000,
USER_COUNT = 1000,
concurrency,
savedTime,
res,
timediff,
ops,
results,
docsPerSecond,
latencyRatio,
currentLatency,
previousLatency;
ops = [
{
op : "find" ,
ns : "test_user_products.user_products" ,
query : {
user : { "#RAND_INT" : [ 0 , USER_COUNT - 1 ] }
},
limit: limit,
fields: { _id: 0, user: 1, product: 1 }
}
];
for (concurrency = 1; concurrency <= 128; concurrency *= 2) {
savedTime = new Date();
res = benchRun({
parallel: concurrency,
host: "localhost",
seconds: seconds,
ops: ops
});
timediff = new Date() - savedTime;
docsPerSecond = res.query * limit;
currentLatency = res.queryLatencyAverageMicros / 1000;
if (previousLatency) {
latencyRatio = currentLatency / previousLatency;
}
results = [
savedTime.getFullYear() + '-' + (savedTime.getMonth() + 1).toFixed(2) + '-' + savedTime.getDate().toFixed(2),
savedTime.getHours().toFixed(2) + ':' + savedTime.getMinutes().toFixed(2),
concurrency,
res.query,
currentLatency,
timediff / 1000,
seconds,
docsPerSecond,
latencyRatio
];
previousLatency = currentLatency;
print(results.join('\t'));
}
Run Code Online (Sandbox Code Playgroud)
结果总是这样(为了便于理解,省略了输出的某些列):
concurrency queries/sec avg latency (ms) latency ratio
1 459.6 2.153609008 -
2 460.4 4.319577324 2.005738882
4 457.7 8.670418178 2.007237636
8 455.3 17.4266174 2.00989353
16 450.6 35.55693474 2.040380754
32 429 74.50149883 2.09527338
64 419.2 153.7325095 2.063482104
128 403.1 325.2151235 2.115460969
Run Code Online (Sandbox Code Playgroud)
如果只有一个客户端处于活动状态,则它可以在10秒测试中每秒执行大约460次查询.查询的平均响应时间约为2毫秒.
当两个客户端同时发送查询时,查询吞吐量维持在每秒约460个查询,表明Mongo没有增加其响应吞吐量.另一方面,平均延迟实际上翻了一番.
对于4个客户,模式继续.相同的查询吞吐量,相对于运行的2个客户端,平均延迟加倍.该列latency ratio是当前测试和之前测试的平均延迟之间的比率.看到它总是显示延迟加倍.
我决定使用不同的实例类型进行测试,改变vCPU的数量和可用RAM的数量.目的是了解添加更多CPU功率时会发生什么.测试的实例类型:
Type vCPUs RAM(GB)
m3.medium 1 3.75
m3.large 2 7.5
m3.xlarge 4 15
m3.2xlarge 8 30
Run Code Online (Sandbox Code Playgroud)
结果如下:


m3.medium
concurrency queries/sec avg latency (ms) latency ratio
1 459.6 2.153609008 -
2 460.4 4.319577324 2.005738882
4 457.7 8.670418178 2.007237636
8 455.3 17.4266174 2.00989353
16 450.6 35.55693474 2.040380754
32 429 74.50149883 2.09527338
64 419.2 153.7325095 2.063482104
128 403.1 325.2151235 2.115460969
Run Code Online (Sandbox Code Playgroud)
m3.large
concurrency queries/sec avg latency (ms) latency ratio
1 855.5 1.15582069 -
2 947 2.093453854 1.811227185
4 961 4.13864589 1.976946318
8 958.5 8.306435055 2.007041742
16 954.8 16.72530889 2.013536347
32 936.3 34.17121062 2.043083977
64 927.9 69.09198599 2.021935563
128 896.2 143.3052382 2.074122435
Run Code Online (Sandbox Code Playgroud)
m3.xlarge
concurrency queries/sec avg latency (ms) latency ratio
1 807.5 1.226082735 -
2 1529.9 1.294211452 1.055566166
4 1810.5 2.191730848 1.693487447
8 1816.5 4.368602642 1.993220402
16 1805.3 8.791969257 2.01253581
32 1770 17.97939718 2.044979532
64 1759.2 36.2891598 2.018374668
128 1720.7 74.56586511 2.054769676
Run Code Online (Sandbox Code Playgroud)
m3.2xlarge
concurrency queries/sec avg latency (ms) latency ratio
1 836.6 1.185045183 -
2 1585.3 1.250742872 1.055438974
4 2786.4 1.422254414 1.13712774
8 3524.3 2.250554777 1.58238551
16 3536.1 4.489283844 1.994745425
32 3490.7 9.121144097 2.031759277
64 3527 18.14225682 1.989033023
128 3492.9 36.9044113 2.034168718
Run Code Online (Sandbox Code Playgroud)
从xlarge类型开始,我们开始看到它最终处理2个并发查询,同时保持查询延迟几乎相同(1.29毫秒).但是,它不会持续太长时间,并且对于4个客户端,它再次使平均延迟加倍.
使用2xlarge类型,Mongo能够处理多达4个并发客户端,而不会过多地增加平均延迟.之后,它再次开始翻倍.
问题是:在进行并发查询方面,可以采取哪些措施来改善Mongo的响应时间?我期望看到在查询吞吐量的增长,我并没有期望看到它加倍平均延迟.它清楚地表明Mongo无法并行化到达的查询.
在限制Mongo的地方存在某种瓶颈,但它肯定无助于增加更多的CPU功率,因为成本太高了.我不认为内存是一个问题,因为我的整个测试数据库很容易适合RAM.还有什么我可以尝试的吗?
您正在使用具有 1 个核心的服务器,并且您正在使用 benchRun。从benchRun 页面:
该 benchRun 命令被设计为 QA 基线性能测量工具;它并不是旨在成为“基准”。
延迟与并发数的比例是否精确得令人怀疑。你确定计算正确吗?我可以相信,随着运行者数量的增加,操作/秒/运行者保持不变,延迟/操作也保持不变 - 然后,如果您添加所有延迟,您会看到像您这样的结果。
| 归档时间: |
|
| 查看次数: |
1166 次 |
| 最近记录: |