MongoDB 中的不稳定插入率
Unstable insert rate in MongoDB
我有一个进程可以每秒生成 20 000 条记录(记录大小 ~30Kb)。我试图尽快将它们插入 MongoDB 的单个实例中。但是我每秒获得约 1500 次插入,速度不稳定,范围从每秒 1000 次插入到 2000 次插入。问题是什么原因以及如何解决它? :) 这是来自 mongostat
2.5 小时的数据:
设置
我是 运行云中的 8 核实例,16Gb 内存,150Gb 硬盘,Ubuntu 18.04,MongoDB 4.0 official docker image。在同一个实例中,运行 2 个工作人员每人每秒生成 10 000 条记录,并且 insert_many
将它们分成 MongoDB 每个块 100 条记录。每条记录在 2 collections cases
和 docs
之间拆分,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_'}
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'}
分析
为了弄清楚发生了什么,我使用 docker stats
和 mongostat
。突出显示关键指标:
我在数据插入期间收集了 2.5 小时的指标,并根据上图绘制了 CPU %
、insert
、dirty
:
可以看到,当脏峰值达到 20% 时,插入率下降,当脏低于 20% 时,插入率上升到 ~2000:
Dirty 在 CPU 激活时下降。可以看到,当 cpu
为 ~300% 时,dirty
开始下降(由于 docker stats
和 mongostat
运行 分开,所以情节有点不正常) ,当 cpu
为 200% 时 dirty
增长回 20% 并且插入速度变慢:
问题
- 我的分析正确吗?这是我第一次使用 MongoDB 所以我可能错了
- 如果分析正确,为什么 MongoDB 不总是使用 300%+ CPU(实例有 8 个核心)来保持低
dirty
和高插入率?是否可以强制它这样做,这是解决我的问题的正确方法吗?
更新
也许 HDD IO 有问题?
我没有记录 IO 使用情况,但是
- 我记得在插入过程中查看了cloud.mongodb.com/freemonitoring,有一个情节叫做"Disk Utilisation",最大50%
- 目前我的问题是插入率不稳定。我可以接受当前每秒最多 2000 次插入。这意味着当前的 HDD 可以处理,对吗?我不明白为什么定期插入率下降到 1000。
关于分片
目前我正在尝试在单机上达到最高性能
解决方案
只需将 HDD 更改为 SSD。
之前:
之后:
在每秒约 1500 次插入的情况下,脏稳定在约 5%。插入和 CPU 使用现在是稳定的。这是我期望看到的行为。 SSD从这个问题的标题中解决了问题"Unstable insert rate in MongoDB"
使用更好的磁盘肯定会提高性能。您还可以监控其他指标。
- 脏字节的百分比表示数据在wiredTiger缓存中被修改但尚未持久化到磁盘。如果磁盘 IOPS 已达到您的配置限制,您应该对其进行监控。使用命令
iostat
监控或从 MongoDB FTDC 数据中获取。
- 当您的 CPU 达到峰值时,监控 CPU 时间是否花费在 iowait 上。如果 iowait % 很高,您有 I/O 阻塞,即更快的磁盘或更多的 IOPS 会有所帮助。
- 监视来自
mongostat
的 qrw(排队的读写请求)和 arw(活动的读写请求)输出。如果这些数字像您的示例输出一样仍然很低,尤其是 qrw,mongo 能够支持您的请求而无需排队请求。
- 通过将注入工作转移到其他实例来避免资源竞争。
- 您可以针对 mongo 数据路径和日志位置使用不同的磁盘分区进一步优化。
- 观察者通常会忽略客户(摄取工作者)的表现。 CPU 峰值可能来自您的工作人员,因此吞吐量较低。使用
top
命令或等效命令监控客户端性能。
希望以上对你有所帮助。
我有一个进程可以每秒生成 20 000 条记录(记录大小 ~30Kb)。我试图尽快将它们插入 MongoDB 的单个实例中。但是我每秒获得约 1500 次插入,速度不稳定,范围从每秒 1000 次插入到 2000 次插入。问题是什么原因以及如何解决它? :) 这是来自 mongostat
2.5 小时的数据:
设置
我是 运行云中的 8 核实例,16Gb 内存,150Gb 硬盘,Ubuntu 18.04,MongoDB 4.0 official docker image。在同一个实例中,运行 2 个工作人员每人每秒生成 10 000 条记录,并且 insert_many
将它们分成 MongoDB 每个块 100 条记录。每条记录在 2 collections cases
和 docs
之间拆分,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_'}
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'}
分析
为了弄清楚发生了什么,我使用 docker stats
和 mongostat
。突出显示关键指标:
我在数据插入期间收集了 2.5 小时的指标,并根据上图绘制了 CPU %
、insert
、dirty
:
可以看到,当脏峰值达到 20% 时,插入率下降,当脏低于 20% 时,插入率上升到 ~2000:
Dirty 在 CPU 激活时下降。可以看到,当 cpu
为 ~300% 时,dirty
开始下降(由于 docker stats
和 mongostat
运行 分开,所以情节有点不正常) ,当 cpu
为 200% 时 dirty
增长回 20% 并且插入速度变慢:
问题
- 我的分析正确吗?这是我第一次使用 MongoDB 所以我可能错了
- 如果分析正确,为什么 MongoDB 不总是使用 300%+ CPU(实例有 8 个核心)来保持低
dirty
和高插入率?是否可以强制它这样做,这是解决我的问题的正确方法吗?
更新
也许 HDD IO 有问题?
我没有记录 IO 使用情况,但是
- 我记得在插入过程中查看了cloud.mongodb.com/freemonitoring,有一个情节叫做"Disk Utilisation",最大50%
- 目前我的问题是插入率不稳定。我可以接受当前每秒最多 2000 次插入。这意味着当前的 HDD 可以处理,对吗?我不明白为什么定期插入率下降到 1000。
关于分片
目前我正在尝试在单机上达到最高性能
解决方案
只需将 HDD 更改为 SSD。
之前:
之后:
在每秒约 1500 次插入的情况下,脏稳定在约 5%。插入和 CPU 使用现在是稳定的。这是我期望看到的行为。 SSD从这个问题的标题中解决了问题"Unstable insert rate in MongoDB"
使用更好的磁盘肯定会提高性能。您还可以监控其他指标。
- 脏字节的百分比表示数据在wiredTiger缓存中被修改但尚未持久化到磁盘。如果磁盘 IOPS 已达到您的配置限制,您应该对其进行监控。使用命令
iostat
监控或从 MongoDB FTDC 数据中获取。 - 当您的 CPU 达到峰值时,监控 CPU 时间是否花费在 iowait 上。如果 iowait % 很高,您有 I/O 阻塞,即更快的磁盘或更多的 IOPS 会有所帮助。
- 监视来自
mongostat
的 qrw(排队的读写请求)和 arw(活动的读写请求)输出。如果这些数字像您的示例输出一样仍然很低,尤其是 qrw,mongo 能够支持您的请求而无需排队请求。 - 通过将注入工作转移到其他实例来避免资源竞争。
- 您可以针对 mongo 数据路径和日志位置使用不同的磁盘分区进一步优化。
- 观察者通常会忽略客户(摄取工作者)的表现。 CPU 峰值可能来自您的工作人员,因此吞吐量较低。使用
top
命令或等效命令监控客户端性能。
希望以上对你有所帮助。