承接国内外服务器租用托管、定制开发、网站代运营、网站seo优化托管接单、网站代更新,新老站点皆可!!咨询QQ:3787320601

记一次MongoDB性能问题(从MySQL迁移到MongoDB)

管理员 2023-07-07 08:03:09 互联网圈 6 ℃ 0 评论 5759字 收藏

记一次MongoDB性能问题(从MySQL迁移到MongoDB)

公司为这个项目专门配备了几台高性能务器,清一色的双路四核超线程CPU,外加32G内存,运维人员安装好MongoDB后,就交我手里了,我习惯于在使用新服务器前先看看相关日志,了解一下基本情况,当我浏览MongoDB日志时,发现一些正告信息:

WARNING: You are running on a NUMA machine. We suggest launching mongod like this to avoid performance problems: numactl –interleave=all mongod [other options]

当时我其实不太清楚NUMA是甚么东西,所以没有处理,只是把问题反馈给了运维人员,后来知道运维人员也没有理睬这茬儿,所以问题的序幕就这样拉开了。

迁移工作需要导入旧数据。MongoDB本身有一个mongoimport工具可供使用,不过它只接受json、csv等格式的源文件,不合适我的需求,所以我没用,而是用PHP写了一个脚本,安稳运行了一段时间后,我发现数据导入的速度降落了,同时PHP抛出异常:

cursor timed out (timeout: 30000, time left: 0:0, status: 0)

我一时判断不出问题所在,想一想先在PHP脚本里加大Timeout的值应付一下:

<?php
MongoCursor::$timeout = ⑴;
?>

惋惜这样并没有解决问题,毛病反倒变着花样的出现了:

max number of retries exhausted, couldn’t send query, couldn’t send query: Broken pipe

接着使用strace跟踪了一下PHP脚本,发现进程卡在了recvfrom操作上:

shell> strace -f -r -p <PID>
recvfrom(<FD>,

通过以下命令查询recvfrom操作的含义:

shell> apropos recvfrom
receive a message from a socket

或依照下面的方式确认一下:

shell> lsof -p <PID>
shell> ls -l /proc/<PID>/fd/<FD>

此时如果查询MongoDB确当前操作,会发现几近每一个操作会消耗大量的时间:

mongo> db.currentOp()

与此同时,运行mongostat的话,结果会显示很高的locked值。

我在网络上找到一篇:MongoDB Pre-Splitting for Faster Data Loading and Importing,看上去和我的问题很类似,不过他的问题实质是由于自动分片致使数据迁移而至,解决方法是使用手动分片,而我并没有使用自动分片,自然不是这个缘由。

询问了几个朋友,有人反应曾遇到过类似的问题,在他的场景里,问题的主要缘由是系统IO操作繁忙时,数据文件预分配梗塞了其它操作,从而致使雪崩效应。

为了验证这类可能,我搜索了一下MongoDB日志:

shell> grep FileAllocator /path/to/log
[FileAllocator] allocating new datafile … filling with zeroes…
[FileAllocator] done allocating datafile … took … secs

我使用的文件系统是ext4(xfs也不错 ),创建数据文件非常快,所以不是这个缘由,但如果有人使用ext3,可能会遇到这类问题,所以或者大概介绍一下怎么解决:

MongoDB按需自动生成数据文件:先是<DB>.0,大小是64M,然后是<DB>.1,大小翻番到128M,到了<DB>.5,大小翻番到2G,其后的数据文件就保持在2G大小。为了不可能出现的问题,可以采取事前手动创建数据文件的策略:

#!/bin/sh

DB_NAME=$1

cd /path/to/$DB_NAME

for INDEX_NUMBER in {5..50}; do
  FILE_NAME=$DB_NAME.$INDEX_NUMBER

  if [ ! -e $FILE_NAME ]; then
    head -c 2146435072 /dev/zero > $FILE_NAME
  fi
done

注:数值2146435072其实不是标准的2G,这是INT整数范围决定的。

最后一个求助方式就是官方论坛了,那里的国际友人建议我检查一下是不是是索引不佳而至,死马当活马医,我激活了Profiler记录慢操作:

mongo> use <DB>
mongo> db.setProfilingLevel(1);

不过结果显示基本都是insert操作(由于我是导入数据为主),本身就不需要索引:

mongo> use <DB>
mongo> db.system.profile.find().sort({$natural:⑴})

问题始终没有得到解决,求人不如求己,我又重复了几次迁移旧数据的进程,结果自然或者老模样,但我发现每当出问题的时候,总有一个名叫irqbalance的进程CPU占用率居高不下,搜索了一下,发现很多介绍irqbalance的文章中都提及了NUMA,让我一下子想起之前在日志中看到的正告信息,我勒个去,居然绕了这么大一个圈圈!安下心来仔细翻阅文档,发现官方其实已有了相关介绍,按以下设置弄定:

shell> echo 0 > /proc/sys/vm/zone_reclaim_mode
shell> numactl –interleave=all mongod [options]

关于zone_reclaim_mode内核参数的说明,可以参考官方文档。

注:从MongoDB1.9.2开始:MongoDB会在启动时自动设置zone_reclaim_mode。

至于NUMA的含义,简单点说,在有多个物理CPU的架构下,NUMA把内存分为本地和远程,每一个物理CPU都有属于自己的本地内存,访问本地内存速度不错于访问远程内存,缺省情况下,每一个物理CPU只能访问属于自己的本地内存。对MongoDB这类需要大内存的服务来讲便可能造成内存不足,NUMA的详细介绍,可以参考老外的文章。

理论上,MySQL、Redis、Memcached等等都可能会遭到NUMA的影响,需要留意。

文章来源:丸子建站

文章标题:记一次MongoDB性能问题(从MySQL迁移到MongoDB)

https://www.wanzijz.com/view/62385.html

X

截屏,微信识别二维码

微信号:weimawl

(点击微信号复制,添加好友)

打开微信