`

mongodb 的一次性能问题

阅读更多
转:[url] http://huoding.com/2011/08/09/104[/url]

记一次MongoDB性能问题
Posted on 2011-08-09
最近忙着把一个项目从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+:check for /proc/sys/vm/zone_reclaim_mode at startup。

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

This entry was posted in Technical and tagged MongoDB, Performance by 老王. Bookmark the permalink.
分享到:
评论

相关推荐

    mysql和mongodb性能对比报告

    本报告旨在通过一系列实验对比MySQL和MongoDB两种不同类型的数据库(关系型数据库与NoSQL数据库)在数据插入性能上的差异,帮助开发者在实际应用中做出更加合适的选择。 #### 测试环境 - **硬件配置**:CPU i5 ...

    MongoDB 性能最佳实践

    - **限制返回结果**:使用 `skip()` 和 `limit()` 函数控制查询返回结果的数量,避免一次性加载大量数据。 5. **索引策略** - **覆盖索引**:创建能够覆盖整个查询的索引,避免回表操作,提升查询速度。 - **...

    MongoDB北京2014 - MongoDB性能扩展 - 唐建法

    - 这样可以直接通过一次查询获取到所有相关的好友状态,大幅提升了查询效率。 **小结**:根据数据访问的方式合理设计数据模型,必要时可以采用数据冗余来提高读取性能。 #### 索引优化 **背景**:索引是提高查询...

    mongodb性能优化.pptx

    默认情况下,它会每隔一秒刷新一次监控数据,也可以通过参数指定不同的刷新间隔。 - **输出字段说明**: - `ns`:命名空间,即数据库名称与集合名称的组合。 - `total`:在该命名空间上MongoDB执行所有操作的总...

    1亿条记录的MongoDB数据库随机查询性能测试

    测试结果显示,在这种情况下,MongoDB的查询速度可以稳定在每秒10万次(10W/S),系统负载(load)保持在1以下。这表明当所有数据都在内存中时,CPU成为主要的性能瓶颈。随着并发查询的增加,当CPU利用率接近上限,...

    MongoDB性能测试报告

    - 一次导入200万条数据与导入100万条数据相比,对导入性能影响不大。 - **磁盘占用情况**: - 单一索引下磁盘占用随数据量增加逐渐增大。 - 复合索引下磁盘占用增长更快。 3. **批量导入性能拐点测试** - **...

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

    MongoDB的性能问题通常涉及到多个方面,包括硬件配置、数据导入方法、系统设置以及数据库的内部操作。在本文中,我们将深入探讨从MySQL迁移到MongoDB时遇到的一些常见问题及解决方案。 首先,当MongoDB在NUMA(Non-...

    MongoDB数据库查询性能提高40倍的经历分享

    数据库性能对软件整体性能有着至关重要的影响,本文给大家分享了一次MongoDB数据库查询性能提高40倍的经历,感兴趣的朋友们可以参考学习。 背景说明 1、数据库:MongoDB 2、数据集: A:字段数不定,这里主要...

    mongodb性能调优执行计划分析

    对于查询优化,我们应该考虑使用更有效率的查询操作符和方法,减少不必要的数据返回量,例如限制查询返回的字段或者使用分页来减少一次查询的数据量。此外,避免使用在大型数据集上效率低下的查询操作符,如正则...

    Mongodb连接池for java

    当连接不再使用时,它们会被放回池中,等待下一次被复用,而非直接关闭。这种方式可以显著提高系统效率,尤其在处理大量并发请求时。 在标签中,“MongoDB”是数据库的名字,“Mongo连接池”指的是针对MongoDB...

    mongodb3.2.4说明文档

    #### 一、MongoDB简介 **1.1 文档型数据库** MongoDB 是一种基于分布式文件存储的开源文档型数据库系统,设计初衷是为了解决传统关系型数据库在处理大规模非结构化数据时存在的局限性。与传统的表格型数据存储方式...

    mongodb 4.0.5 我的第一次数据库集群(linux).zip

    MongoDB 是一个高性能、开源、无模式的分布式文档数据库,被广泛用于开发现代应用程序,特别是那些需要处理大量数据和高并发场景的应用。在本案例中,我们关注的是 MongoDB 4.0.5 版本的集群搭建过程,该版本引入了...

    mongodb源码

    通过深入研究`mongodb-mongo-397660d`源码,你可以了解MongoDB如何处理数据存储、网络通信、查询优化等核心功能,这对于开发自定义插件、解决性能问题或进行大规模部署具有重要意义。同时,这也是一次深入学习分布式...

    php Mongodb 操作类

    - 批量操作:支持一次处理多个文档的写入或删除操作。 - 键索引:创建、查看和删除集合上的索引,以优化查询性能。 - 数据库管理:获取数据库信息,如集合列表,执行数据库级别的操作。 4. **使用示例** 使用这...

    MongoDB C Driver 1.13.0

    5. **批量操作**:为了优化性能,驱动提供了批量操作API,允许一次性发送多个插入、更新或删除操作,减少了网络往返次数。 6. **游标**:`mongoc_cursor_t`对象用于遍历查询结果,它实现了迭代器的概念,可以在...

Global site tag (gtag.js) - Google Analytics