下面文章转载自火丁笔记,原作者描述了一次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性能问题的更多相关文章

  1. MongoDB性能篇之创建索引,组合索引,唯一索引,删除索引和explain执行计划

    这篇文章主要介绍了MongoDB性能篇之创建索引,组合索引,唯一索引,删除索引和explain执行计划的相关资料,需要的朋友可以参考下 一.索引 MongoDB 提供了多样性的索引支持,索引信息被保存 ...

  2. MongoDB 性能优化五个简单步骤

    MongoDB 一直是最流行的 NoSQL,而根据 DB-Engines Ranking 最新的排行,时下 MongoDB 已经击败 PostgreSQL 跃居数据库总排行的第四位,仅次于 Oracl ...

  3. 分布式监控系统Zabbix3.4-针对MongoDB性能监控操作笔记

    公司在IDC机房的一台服务器上部署了MongoDB,由于所存储的业务数据比较重要,所以对MongoDB的监控显得尤为重要!Zabbix监控MongoDB性能的原理:通过echo "db.se ...

  4. mongodb可以通过profile来监控数据 (mongodb性能优化)

    mongodb可以通过profile来监控数据 (mongodb性能优化)   开启 Profiling  功能 ,对慢查询进行优化: mongodb可以通过profile来监控数据,进行优化. 查看 ...

  5. 开发高性能的MongoDB应用—浅谈MongoDB性能优化

    关联文章索引: 大数据时代的数据存储,非关系型数据库MongoDB 性能与用户量 “如何能让软件拥有更高的性能?”,我想这是一个大部分开发者都思考过的问题.性能往往决定了一个软件的质量,如果你开发的是 ...

  6. Mongodb性能调优

    摘要 1. Mongodb 适用场景简介 2. Mongodb 性能监控与分析 3. Mongodb 性能优化建议 关于Mongodb的几个大事件 1.根据美国数据库知识大全官网发布的DB热度排行,M ...

  7. 011.MongoDB性能监控

    一 MongoDB 监控 1.1 监控概述 MongoDB自带了mongostat 和 mongotop 这两个命令来监控MongoDB的运行情况.这两个命令用于处理MongoDB数据库变慢等等问题非 ...

  8. MongoDB性能优化

    一.索引 MongoDB 提供了多样性的索引支持,索引信息被保存在system.indexes 中,且默认总是为_id创建索引,它的索引使用基本和MySQL 等关系型数据库一样.其实可以这样说说,索引 ...

  9. MongoDB性能监控

    1.mongostat 查看运行中的mongodb实例的统计信息 重要指标说明: getmore: 通常发生在结果集比较大的查询时,第一个query返回了部分结果,后续的结果是通过getmore来获取 ...

随机推荐

  1. 21天学通C++学习笔记(三):变量和常量

    1. 简述 内存是一种临时存储器,也被称为随机存取存储器(RAM),所有的计算机.智能手机及其他可编程设备都包含微处理器和一定数量的内存,用地址来定位不同的存储区域,像编号一样. 硬盘可以永久的存储数 ...

  2. 自建脚手架之配置中心--LightConf的实现

    常规项目开发过程中, 通常会将配置信息位于在项目resource目录下的properties文件文件中, 配置信息通常包括有: jdbc地址配置.redis地址配置.活动开关--等等.因此每次上线或者 ...

  3. 【大数据之数据仓库】GreenPlum优化器对比测试

    在< [大数据之数据仓库]选型流水记>一文中有提及,当时没有测试GreenPlum的quicklz压缩算法和ORCA查询优化器,考虑到quicklz压缩算法因为版权问题不会开源(详情请参阅 ...

  4. 趣图:向客户介绍的产品VS实际开发的产品

      趣图:客户需求 vs 最终产品 趣图:你永远想不到用户怎么使用你的产品

  5. 记录一些好用的iOS第三方库

    CBStoreHouseRefreshControl:一个效果很酷炫的下拉刷新控件. ZLSwipeableView:ZLSwipeableView是一个方便做出卡片效果的UI库,支持各种卡片的滑动效 ...

  6. 修复win10无法双击打开txt文档.reg

    Windows Registry Editor Version 5.00[HKEY_CLASSES_ROOT\.txt]@="txtfile""Content Type& ...

  7. gitlab 服务器的搭建与使用全过程(二)

    <gitlab操作手册 1.0 > 此手册适用于 Mac 计算机 第一步:根据从管理员得到的用户名和初始密码登陆并修改密码.新密码不得少于8个字符 第二步:在自己的电脑上创建密钥,并提交提 ...

  8. 【解决】Linux Tomcat启动慢--Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [236,325] milliseconds

    一.背景 今天部署项目到tomcat,执行./startup.sh命令之后,访问项目迟迟加载不出来,查看日志又没报错(其实是我粗心了,当时tomcat日志还没打印完),一开始怀疑是阿里云主机出现问题, ...

  9. Python web前端 05 JavaScript

    Python web前端 05 JavaScript 一.获取元素 1.初识JavaScript /* .. */ #这是多行注释 // #这是单行注释 #JavaScript是一种脚本语言,是一种动 ...

  10. [BZOJ 4850][Jsoi2016]灯塔

    传送门 #include <bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=a;i<=b;++i) ...