记一次MongoDB性能问题
下面文章转载自火丁笔记,原作者描述了一次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 = -1; ?>
可惜这样并没有解决问题,错误反倒变着花样的出现了:
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:-1})
…
问题始终没有得到解决,求人不如求己,我又重复了几次迁移旧数据的过程,结果自然还是老样子,但我发现每当出问题的时候,总有一个名叫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的影响,需要留意。
***********************************************************************
对于罪魁祸首,作者留给大家去学习,在这里可以给大家做一个简单的描述,先解释几个概念。
NUMA:NUMA是多核心CPU架构中的一种,其全称为Non-Uniform Memory Access,简单来说就是在多核心CPU中,机器的物理内存是分配给各个核的,架构简图如下所示:
每个核访问分配给自己的内存会比访问分配给其它核的内存要快,有下面几种访问控制策略:
1.缺省(default):总是在本地节点分配(分配在当前进程运行的节点上);
2.绑定(bind):强制分配到指定节点上;
3.交叉(interleave):在所有节点或者指定的节点上交织分配;
4.优先(preferred):在指定节点上分配,失败则在其他节点上分配。
上面文章中最后使用numactl –interleave命令就是指定其为交叉共享模式。
irqbalance:这是作者在上面提到的一个占用CPU的进程,这个进程的作用是在多核心CPU的操作系统中,分配系统中断信号的。参见:irqbalance.org
概念说完了,下面是上面问题的简单描述:
我们知道虚拟内存机制是通过一个中断信号来通过进行内存swap的,所以这个irqbalance进程忙,是一个危险信号,在这里是由于在进行频繁 的内存交换。这种频繁交换现象称为swap insanity,在MySQL中经常提到,也就是在NUMA框架中,采用不合适的策略,导致核心只能从指定内存块节点上分配内存,即使总内存还有富余, 也会由于当前节点内存不足时产生大量的swap操作。
from: http://blog.163.com/lgh_2002/blog/static/4401752620130152575313/
记一次MongoDB性能问题的更多相关文章
- MongoDB性能篇之创建索引,组合索引,唯一索引,删除索引和explain执行计划
这篇文章主要介绍了MongoDB性能篇之创建索引,组合索引,唯一索引,删除索引和explain执行计划的相关资料,需要的朋友可以参考下 一.索引 MongoDB 提供了多样性的索引支持,索引信息被保存 ...
- MongoDB 性能优化五个简单步骤
MongoDB 一直是最流行的 NoSQL,而根据 DB-Engines Ranking 最新的排行,时下 MongoDB 已经击败 PostgreSQL 跃居数据库总排行的第四位,仅次于 Oracl ...
- 分布式监控系统Zabbix3.4-针对MongoDB性能监控操作笔记
公司在IDC机房的一台服务器上部署了MongoDB,由于所存储的业务数据比较重要,所以对MongoDB的监控显得尤为重要!Zabbix监控MongoDB性能的原理:通过echo "db.se ...
- mongodb可以通过profile来监控数据 (mongodb性能优化)
mongodb可以通过profile来监控数据 (mongodb性能优化) 开启 Profiling 功能 ,对慢查询进行优化: mongodb可以通过profile来监控数据,进行优化. 查看 ...
- 开发高性能的MongoDB应用—浅谈MongoDB性能优化
关联文章索引: 大数据时代的数据存储,非关系型数据库MongoDB 性能与用户量 “如何能让软件拥有更高的性能?”,我想这是一个大部分开发者都思考过的问题.性能往往决定了一个软件的质量,如果你开发的是 ...
- Mongodb性能调优
摘要 1. Mongodb 适用场景简介 2. Mongodb 性能监控与分析 3. Mongodb 性能优化建议 关于Mongodb的几个大事件 1.根据美国数据库知识大全官网发布的DB热度排行,M ...
- 011.MongoDB性能监控
一 MongoDB 监控 1.1 监控概述 MongoDB自带了mongostat 和 mongotop 这两个命令来监控MongoDB的运行情况.这两个命令用于处理MongoDB数据库变慢等等问题非 ...
- MongoDB性能优化
一.索引 MongoDB 提供了多样性的索引支持,索引信息被保存在system.indexes 中,且默认总是为_id创建索引,它的索引使用基本和MySQL 等关系型数据库一样.其实可以这样说说,索引 ...
- MongoDB性能监控
1.mongostat 查看运行中的mongodb实例的统计信息 重要指标说明: getmore: 通常发生在结果集比较大的查询时,第一个query返回了部分结果,后续的结果是通过getmore来获取 ...
随机推荐
- 【转】Android自定义控件(二)——有弹性的ScrollView
原文地址:http://blog.csdn.net/a105865708/article/details/17784041 实现了当手指滑动到ScrollView的顶部.底部时, 可以继续的向上.向下 ...
- 【转】ANDROID自定义视图——onMeasure,MeasureSpec源码 流程 思路详解
原文地址:http://blog.csdn.net/a396901990/article/details/36475213 简介: 在自定义view的时候,其实很简单,只需要知道3步骤: 1.测量—— ...
- spring深入了解心得
spring 主要核心组件 :Core.上下文(Context) .实体(Bean): spring 主要由两大特色:控制反转(IOC).面向对象(AOP): spring中Core主要用于组建Bea ...
- javascript ie8兼容 a标签href javascript:void(0);
ie8兼容 a标签href javascript:void(0); 尽量不要用javascript:协议做为A的href属性,这样不仅会导致不必要的触发window.onbeforeunload事件;
- 老司机图文教程教你如何免费下载腾讯视频的视频mp4(直接下载到,不用qlv格式转mp4格式,亲测)
关于如何下载到腾讯视频的mp4这个问题,大家想必经过多翻搜索,都未必找到满意的答案吧. 下载微信公众号文章中引用的腾讯视频的方法也是一样适用本方法. 因为用腾讯视电脑客户端和手机APP下载到的都是QL ...
- vs引入资源
把资源放在程序目录中,然后点击显示所有文件,然后在资源上右键“包括在项目中”
- JavaWeb应用中初始化Log4j的两种方式
本文主要介绍了普通JavaWeb应用(基于Tomcat)中初始化Log4j的两种方式: 1.通过增加 InitServlet ,设置令其自启动来初始化 Log4j . 2.通过监听器 ServletC ...
- Sample-Code:Translator
<h2>My Spanish Translator</h2> <p> Enter your text in English: </p> <p&g ...
- mysql 外键问题
清空.删除具有外键约束的表时报ERROR 1701(42000)的解决 解决方法: 解除外键约束mysql> set foreign_key_checks=0; 删除表后添加外键约束 mysql ...
- python学习,day2:列表的使用,增删改合并等
# coding=utf-8 # Author: RyAn Bi names = ['A','B','C','D'] print(names) print(names[0]) #从0开始记录 prin ...