MongoDB中的插入率不稳定

ale*_*kuk 6 crud mongodb nosql

我有一个每秒可以生成20 000条记录的过程(记录大小~30Kb).我试图尽可能快地将它们插入到MongoDB的单个实例中.但我每秒得到约1500次插入,不稳定的速率范围从1000次插入到每秒2000次插入.问题是原因是什么以及如何解决?:)这是mongostat2.5小时的数据:

建立

我在云中运行实例,包括8核,16Gb RAM,150Gb硬盘,Ubuntu 18.04,MongoDB 4.0 官方 docker 镜像.在同一个实例上运行2个工作程序,每个工作程序每秒生成10 000条记录,并将insert_many它们分成每个块的MongoDB 100条记录.每个记录2个集合之间划分casesdocs,docs使用zlib压缩.cases记录平均大小约为1Kb.随机记录为例:

{'info': {'judge': '?????? ????? ??????????', 'decision': '???????? ? ???????????? ?? ????? ????????????', 'entry_date': datetime.datetime(2017, 1, 1, 0, 0), 'number': '12-48/2017 (12-413/2016;)', 'decision_date': datetime.datetime(2017, 2, 9, 0, 0)}, 'acts': [{'doc': ObjectId('5c3c76543d495a000c97243b'), 'type': '???????'}], '_id': ObjectId('5c3c76543d495a000c97243a'), 'sides': [{'name': '???????? ?. ?.', 'articles': '????: ??. 5.27.1 ?.4'}], 'history': [{'timestamp': datetime.datetime(2017, 1, 1, 15, 6), 'type': '????????? ???????? ? ???????????? ?????'}, {'timestamp': datetime.datetime(2017, 2, 9, 16, 0), 'type': '???????? ?????????', 'decision': '???????? ? ???????????? ?? ????? ????????????'}, {'timestamp': datetime.datetime(2017, 2, 17, 15, 6), 'type': '???? ????? ? ????? ????????? ????????????????'}, {'timestamp': datetime.datetime(2017, 2, 17, 15, 7), 'type': '???????? ????? ??????? (???????????) ? ?????. ? ??. 2, 2.1, 2.2 ??. 30.8 ???? ??'}, {'timestamp': datetime.datetime(2017, 3, 13, 16, 6), 'type': '???????? ? ???????? ????'}, {'timestamp': datetime.datetime(2017, 3, 14, 16, 6), 'type': '???? ?????????'}, {'timestamp': datetime.datetime(2017, 3, 29, 14, 33), 'type': '???? ???????? ? ?????'}], 'source': {'date': datetime.datetime(2017, 1, 1, 0, 0), 'engine': 'v1', 'instance': 'appeal', 'host': 'bratsky.irk.sudrf.ru', 'process': 'adm_nar', 'crawled': datetime.datetime(2018, 12, 22, 8, 15, 7), 'url': 'https://bratsky--irk.sudrf.ru/modules.php?name=sud_delo&srv_num=1&name_op=case&case_id=53033119&case_uid=A84C1A34-846D-4912-8242-C7657985873B&delo_id=1502001'}, 'id': '53033119_A84C1A34-846D-4912-8242-C7657985873B_1_'}
Run Code Online (Sandbox Code Playgroud)

docs 记录平均约为30Kb:

{'_id': ObjectId('5c3c76543d495a000c97243b'), 'data': 'PEhUTUw+PEhFQUQ+DQo8TUVUQSBodHRwLWVxdWl2PUNvbnRlbnQtVHlwZSBjb250ZW50PSJ0ZXh0L2h0bWw7IGNoYXJzZXQ9V2luZG93cy0xMjUxIj4NCjxTVFlMRSB0eXBlPXRleHQvY3NzPjwvU1RZTEU+DQo8L0hFQUQ+DQo8Qk9EWT48U1BBTiBzdHlsZT0iVEVYVC1BTElHTjoganVzdGlmeSI+DQo8UCBzdHlsZT0iVEVYVC1JTkRFTlQ6IDAuNWluOyBURVhULUFMSUdOOiBjZW50ZXIiPtCgINCVINCoINCVINCdINCYINCVPC9QPg0KPFAgc3R5bGU9IlRFWFQtSU5ERU5UOiAwLjVpbjsgVEVYVC1BTElHTjoganVzdGlmeSI+0LMuINCR0YDQsNGC0YHQuiAwOSDRhNC10LLRgNCw0LvRjyAyMDE3INCz0L7QtNCwPC9QPg0KPFAgc3R5bGU9IlRFWFQtSU5ERU5UOiAwLjVpbjsgVEVYVC1BTElHTjoganVzdGlmeSI+0KHRg9C00YzRjyDQkdGA0LDRgtGB0LrQvtCz0L4g0LPQvtGA0L7QtNGB0LrQvtCz0L4g0YHRg9C00LAg0JjRgNC60YPRgtGB0LrQvtC5INC+0LHQu9Cw0YHRgtC4INCe0YDQu9C+0LLQsCDQni7Qki4sINGA0LDRgdGB0LzQvtGC0YDQtdCyINCw0LTQvNC40L3QuNGB0YLRgNCw0YLQuNCy0L3QvtC1INC00LXQu9C+IOKEliAxMi00OC8yMDE3INC/0L4g0LbQsNC70L7QsdC1INC40L3QtNC40LLQuNC00YPQsNC70YzQvdC+0LPQviDQv9GA0LXQtNC/0YDQuNC90LjQvNCw0YLQtdC70Y8g0JrRg9C30L3QtdGG0L7QstCwIDxTUE.....TlQ6IDAuNWluOyBURVhULUFMSUdOOiBqdXN0aWZ5Ij7QoNC10YjQtdC90LjQtSDQvNC+0LbQtdGCINCx0YvRgtGMINC+0LHQttCw0LvQvtCy0LDQvdC+INCyINCY0YDQutGD0YLRgdC60LjQuSDQvtCx0LvQsNGB0YLQvdC+0Lkg0YHRg9C0INCyINGC0LXRh9C10L3QuNC1IDEwINGB0YPRgtC+0Log0YEg0LzQvtC80LXQvdGC0LAg0L/QvtC70YPRh9C10L3QuNGPINC10LPQviDQutC+0L/QuNC4LjwvUD4NCjxQIHN0eWxlPSJURVhULUlOREVOVDogMC41aW47IFRFWFQtQUxJR046IGp1c3RpZnkiPtCh0YPQtNGM0Y8g0J4u0JIuINCe0YDQu9C+0LLQsDwvUD48L1NQQU4+PC9CT0RZPjwvSFRNTD4=', 'extension': '.html'}
Run Code Online (Sandbox Code Playgroud)

分析

为了弄清楚是怎么回事我用的docker statsmongostat.关键指标突出显示:

余数据插入和绘图过程中收集2.5小时度量CPU %,insert,dirty从上面的图片:

可以看出,当脏污率达到20%时,插入率下降,当脏污低于20%时,插入率上升到~2000:

CPU处于活动状态时脏了.人们可以看到,当cpu300%dirty开始下降时(情节有点不合适,因为docker stats并且mongostat单独运行),何时cpu200%dirty增长回20%并且插入速度减慢:

  1. 我的分析是否正确?这是我第一次使用MongoDB,所以我可能错了
  2. 如果分析正确,为什么MongoDB并不总是使用300%+ CPU(实例有8个内核)来保持dirty低和插入率高?是否有可能强制它这样做,这是解决我的问题的正确方法吗?

更新

也许HDD IO是一个问题?

我没有记录IO利用率,但是

  1. 我记得在插入过程中查看cloud.mongodb.com/freemonitoring,有一个名为"磁盘利用率"的图,最大值为50%
  2. 目前我的问题是插入率不稳定.我最好每秒最多2000次插入.这意味着当前的HDD可以处理它,对吗?我不明白为什么要定期将速率下降到1000.

关于分片

目前我正试图在单台机器上达到最大性能

只需将HDD更改为SSD即可.

之前: 之前

后: 后

每秒约1500次插入,脏污稳定在~5%.插入和CPU使用现在稳定.这是我期望看到的行为.SSD解决了这个问题标题"MongoDB中的不稳定插入率"的问题

sim*_*gix 0

使用更好的磁盘肯定会提高性能。您还可以监控其他指标。

  • 脏字节百分比表示数据在wiredTiger缓存中被修改但尚未持久化到磁盘。如果磁盘 IOPS 达到了您的配置限制,您应该监控它。使用命令iostat监控或从 MongoDB FTDC 数据获取。
  • 当您的 CPU 出现峰值时,监视 CPU 时间是否花费在iowait上。如果iowait %较高,则表明存在 I/O 阻塞,即更快的磁盘或更多的 IOPS 会有所帮助。
  • 监视输出中的qrw(排队的读取和写入请求)和arw(活动的读取和写入请求)mongostat。如果这些数字像您的示例输出一样保持较低,尤其是qrw,则 mongo 能够支持您的请求,而无需对请求进行排队。
  • 通过将注入工作转移到其他实例来避免资源竞争。
  • 您可以使用不同的磁盘分区来进一步优化 mongo 数据路径和日志位置。
  • 观察者通常会忽略客户端(摄取工作人员)的表现。CPU 峰值可能来自您的工作人员,因此吞吐量较低。使用命令或等效命令监视客户端性能top

希望以上帮助。