1.公司业务调整,把一部分数据由Redis转至MongoDB,业务在测试环境正常,生产环境上线后发现压力一上来MongoDB的服务直接把CPU占满了,和开发的同学分析了一下也参考了一下百度上类似的问题,最后定位原因:未使用索引。

解决方法很简单:对应的关键字段创建索引即可。

参考命令如下:

>use Data;                                            #进入数据库Data,注意区分大小写;

>db.stats();                                #查看数据库的状态;

>db.getCollectionNames();        #查看所有表名;

>db.dynamic.find().limit(5);        #查看dynamic表的前5条数据;

>db.dynamic.find().count();        #统计dynamic表总共有多少数据;

>db.dynamic.getIndexes();        #查询表dynamic的索引

#新建索引:对dynamic的score字段以backgroud方式建立索引

>db.dynamic.ensureIndex({score:1} , {backgroud:true});

#状态查看:20秒,每秒更新一次

mongostat -h 80.81.2.3 -p 27017 --rowcount 20 1

mingotop   -h 80.81.2.3 -p 27017 --rowcount 20 1

开始创建索引的字段没找准,效果不明显,后来对关键字段创建索引后CPU使用率断崖式下跌。

分析MongoDB数据库正在执行的请求

  1. 通过Mongo Shell连接实例。
  2. 执行db.currentOp()命令,查看数据库当前正在执行的操作。

分析MongoDB数据库的慢请求

云数据库MongoDB默认开启了慢请求Profiling ,系统自动地将请求时间超过100ms的执行情况记录到对应数据库下的system.profile集合里。

  1. 通过 Mongo Shell 连接实例。
  2. 通过use <database>命令进入指定数据库。
    use mongodbtest
  3. 执行如下命令,查看该数据下的慢请求日志。
    db.system.profile.find().pretty()
  4. 分析慢请求日志,查找引起MongoDB CPU使用率升高的原因。
    以下为某个慢请求日志示例,可查看到该请求进行了全表扫描,扫描了11000000个文档,没有通过索引进行查询。

     
    {
    "op" : "query",
    "ns" : "123.testCollection",
    "command" : {
    "find" : "testCollection",
    "filter" : {
    "name" : "zhangsan"
    },
    "$db" : "123"
    },
    "keysExamined" : 0,
    "docsExamined" : 11000000,
    "cursorExhausted" : true,
    "numYield" : 85977,
    "nreturned" : 0,
    "locks" : {
    "Global" : {
    "acquireCount" : {
    "r" : NumberLong(85978)
    }
    },
    "Database" : {
    "acquireCount" : {
    "r" : NumberLong(85978)
    }
    },
    "Collection" : {
    "acquireCount" : {
    "r" : NumberLong(85978)
    }
    }
    },
    "responseLength" : 232,
    "protocol" : "op_command",
    "millis" : 19428,
    "planSummary" : "COLLSCAN",
    "execStats" : {
    "stage" : "COLLSCAN",
    "filter" : {
    "name" : {
    "$eq" : "zhangsan"
    }
    },
    "nReturned" : 0,
    "executionTimeMillisEstimate" : 18233,
    "works" : 11000002,
    "advanced" : 0,
    "needTime" : 11000001,
    "needYield" : 0,
    "saveState" : 85977,
    "restoreState" : 85977,
    "isEOF" : 1,
    "invalidates" : 0,
    "direction" : "forward",
    ....in"
    }
    ],
    "user" : "root@admin"
    }

通常在慢请求日志中,您需要重点关注以下几点。

  • 全表扫描(关键字: COLLSCAN、 docsExamined )

    • 全集合(表)扫描COLLSCAN 。

      当一个操作请求(如查询、更新、删除等)需要全表扫描时,将非常占用CPU资源。在查看慢请求日志时发现COLLSCAN关键字,很可能是这些查询占用了你的CPU资源。

       
      说明 如果这种请求比较频繁,建议对查询的字段建立索引的方式来优化。
    • 通过查看docsExamined的值,可以查看到一个查询扫描了多少文档。该值越大,请求所占用的CPU开销越大。
  • 不合理的索引(关键字: IXSCAN、keysExamined )

    通过查看keysExamined字段,可以查看到一个使用了索引的查询,扫描了多少条索引。该值越大,CPU开销越大。

    如果索引建立的不太合理,或者是匹配的结果很多。这样即使使用索引,请求开销也不会优化很多,执行的速度也会很慢。

    如下所示,假设某个集合的数据,x字段的取值很少(假设只有1、2),而y字段的取值很丰富

     { x: 1, y: 1 }
    { x: 1, y: 2 }
    { x: 1, y: 3 }
    ......
    { x: 1, y: 100000}
    { x: 2, y: 1 }
    { x: 2, y: 2 }
    { x: 2, y: 3 }
    ......
    { x: 1, y: 100000}

    要实现 {x: 1, y: 2} 这样的查询。

     
    db.createIndex( {x: 1} )         效果不好,因为x相同取值太多
    db.createIndex( {x: 1, y: 1} ) 效果不好,因为x相同取值太多
    db.createIndex( {y: 1 } ) 效果好,因为y相同取值很少
    db.createIndex( {y: 1, x: 1 } ) 效果好,因为y相同取值少

    关于{y: 1} 与 {y: 1, x: 1} 的区别,可参考MongoDB索引原理复合索引官方文档

  • 大量数据排序(关键字: SORT、hasSortStage )
     
  • 当查询请求里包含排序的时候, system.profile 集合里的 hasSortStage 字段会为 true 。如果排序无法通过索引满足, MongoDB 会在查询结果中进行排序。而排序这个动作将非常消耗CPU资源,这种情况需要对经常排序的字段建立索引的方式进行优化。
  • 连接数

1、mongodb最大的连接数是819,在启动里面加参数 --maxConns=3000重启mongodb服务后最大连接数还是819。

2、其实是linux系统的限制,Linux系统默认一个进程最大文件打开数目为1024。需要修改此限制
3、因为将mongodb添加到开机启动里面,需要在rc.local文件下面加ulimit -n 的限制
vi /etc/rc.local
ulimit -n 20000
rm /usr/mongodb/log/mongodb.log
/usr/mongodb/bin/mongod --dbpath=/usr/mongodb/data/ --logpath=/usr/mongodb/log/mongodb.log --master --oplogSize 200
然后重启机器再次查看mongodb的最大连接数发现变了
[root@DB192168129044 bin]# ./mongo
MongoDB shell version: 2.2.0
connecting to: test
> db.serverStatus()。connections;
{ “current” : 1, “available” : 15999 }

MongoDB的CPU使用率高最佳实践

问题症状

mongodb 实例在日常使用中,有时会出现 CPU使用达到 80%以上 的情况。

问题原因

1、耗时的请求

1.1、全表扫描

关键字:COLLSCAN、 docsExamined

1.2、不合理的索引

关键字:IXSCAN、keysExamined

1.3、大量数据排序

关键字:SORT、hasSortStage

2、服务器能力达到上限

整个数据库的查询非常合理,所有的请求都是高效的走了索引,基本没有优化的空间了,就是机器的服务能力已经达到上限了,应该升级配置了

3、服务器被攻击

通过分析端口连接数,来源IP,日志确认来源IP的访问内容

3.1 查看端口连接数

[root@MONGO-17 ~]# netstat -anp | grep 22001 | wc -l

3.2 查看端口连接来源IP

[root@MONGO-17 ~]# netstat -n | grep 22001 |awk '/^tcp/ {print $5}'| awk -F: '{print $1}' | sort | uniq -c | sort -rn

3.3 查看日志来源IP是什么程序访问

[root@mnkj-db02 data]# netstat -anp | egrep 120.78.231.86:5[0-9]*
tcp 50 0 120.78.231.86:55402 106.11.68.13:80 ESTABLISHED 21343/wrapper

排查步骤

1、资源查看

1.1 占用CPU高的进程

[root@MONGO-17 ~]# top
top - 10:04:09 up 131 days, 17:30, 1 user, load average: 3.85, 2.97, 2.81
Tasks: 189 total, 1 running, 188 sleeping, 0 stopped, 0 zombie
%Cpu0 : 35.6 us, 2.4 sy, 0.0 ni, 61.7 id, 0.0 wa, 0.0 hi, 0.3 si, 0.0 st
%Cpu1 : 37.7 us, 3.3 sy, 0.0 ni, 58.7 id, 0.0 wa, 0.0 hi, 0.3 si, 0.0 st
%Cpu2 : 59.5 us, 4.1 sy, 0.0 ni, 36.5 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu3 : 32.6 us, 3.4 sy, 0.0 ni, 64.1 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu4 : 38.7 us, 3.4 sy, 0.0 ni, 57.6 id, 0.0 wa, 0.0 hi, 0.3 si, 0.0 st
%Cpu5 : 32.9 us, 2.4 sy, 0.0 ni, 64.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu6 : 44.0 us, 2.7 sy, 0.0 ni, 53.4 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu7 : 42.4 us, 3.7 sy, 0.0 ni, 53.6 id, 0.0 wa, 0.0 hi, 0.3 si, 0.0 st
%Cpu8 : 45.1 us, 3.4 sy, 0.0 ni, 51.2 id, 0.0 wa, 0.0 hi, 0.3 si, 0.0 st
%Cpu9 : 66.9 us, 5.4 sy, 0.0 ni, 27.4 id, 0.0 wa, 0.0 hi, 0.3 si, 0.0 st
%Cpu10 : 35.8 us, 3.4 sy, 0.0 ni, 60.8 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu11 : 34.3 us, 3.5 sy, 0.0 ni, 59.2 id, 0.0 wa, 0.0 hi, 3.1 si, 0.0 st
%Cpu12 : 37.5 us, 2.7 sy, 0.0 ni, 59.8 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu13 : 45.3 us, 3.7 sy, 0.0 ni, 51.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu14 : 68.9 us, 2.7 sy, 0.0 ni, 28.4 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu15 : 43.6 us, 2.7 sy, 0.0 ni, 53.4 id, 0.0 wa, 0.0 hi, 0.3 si, 0.0 st
KiB Mem : 32780412 total, 274896 free, 20882888 used, 11622628 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 11440020 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
24406 root 20 0 28.204g 0.018t 5976 S 919.6 58.4 477312:14 mongod
24297 root 20 0 3008300 1.148g 6456 S 0.7 3.7 1354:41 mongod
7823 zabbix 20 0 15372 1028 804 S 0.3 0.0 3:46.26 zabbix_agentd

1.2 确定占用CPU高的进程和线程

# 获取进程id 24406
[root@MONGO-17 ~]# ps -ef | grep 24406
/opt/mongodb/bin/mongod --shardsvr --replSet shard17 --port 22001 --dbpath /data/mongodb/shard1/data --auth --keyFile=/opt/mongodb/key/authfile --logpath /data/mongodb/shard1/logs/shard.log --fork # 查看进程的线程top -p 24406 按 shift+h 查看cpu高的线程,查找线程点用cpu高且cpu时间很长
[root@MONGO-17 tmp]# top -p 24406
top - 13:44:28 up 131 days, 21:10, 2 users, load average: 1.19, 2.34, 2.17
Tasks: 1 total, 0 running, 1 sleeping, 0 stopped, 0 zombie
%Cpu(s): 1.4 us, 0.2 sy, 0.0 ni, 98.4 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 32780412 total, 3806372 free, 20931264 used, 8042776 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 11391328 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
24406 root 20 0 28.199g 0.018t 5772 S 23.6 58.5 477924:55 mongod
top - 13:46:33 up 131 days, 21:13, 2 users, load average: 3.11, 2.37, 2.18
Threads: 812 total, 5 running, 807 sleeping, 0 stopped, 0 zombie
%Cpu(s): 31.7 us, 1.2 sy, 0.0 ni, 67.0 id, 0.0 wa, 0.0 hi, 0.1 si, 0.0 st
KiB Mem : 32780412 total, 3767812 free, 20957716 used, 8054884 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 11363284 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
25421 root 20 0 28.348g 0.018t 5772 R 95.4 58.5 4544:58 conn173
14810 root 20 0 28.255g 0.021t 5592 R 99.7 67.3 0:11.06 conn3223924
2360 root 20 0 28.255g 0.021t 5592 R 93.0 67.3 133:33.64 conn3118924
11174 root 20 0 28.255g 0.021t 5592 R 46.5 67.3 182:49.85 conn3125456
1514 root 20 0 28.255g 0.021t 5592 S 41.2 67.3 191:05.51 conn3118283
15026 root 20 0 28.255g 0.021t 5592 R 28.9 67.3 159:31.74 conn3128335
11941 root 20 0 28.218g 0.018t 5776 R 99.7 58.7 0:25.09 conn3221759
12277 root 20 0 28.218g 0.018t 5776 R 99.7 58.7 0:11.82 conn3222028

1.3 分析占用CPU高的线程ID执行内容

# 获取12月14号00:00pm 到12月14号07:30pm执行超过1000ms查询
[root@MONGO-17 tmp]# mlogfilter /data/mongodb/shard1/logs/shard.log --slow 1000 --from 2017-12-14 00:00 --to 2017-12-14 7:30 > /tmp/121400_07.log # 截取线程ID 25421的线程执行的内容
[root@MONGO-17 tmp]# sed -n '/\[conn173\]/p' 121400.log
2017-12-14T14:00:56.590+0800 W COMMAND [conn173] Use of the aggregate command without the 'cursor' option is deprecated. See http://dochub.mongodb.org/core/aggregate-without-cursor-deprecation.

1.4 分析mongodb shard.log日志

#安装mtools

# 获取12月13号凌晨开始执行超过1000ms的前20条查询,结果见附件《121300_20.txt》
[root@MONGO-17 logs]# mlogfilter shard.log --from 2017-12-13 0:00 --slow 1000 | head -n20 > /tmp/121300_20.txt # 获取日志基本信息
[root@MONGO-17 logs]# mloginfo shard.log
source: shard.log
host: MONGO-17:22001
start: 2017 Sep 12 01:08:48.487
end: 2017 Dec 14 10:15:56.643
date format: iso8601-local
length: 33471780
binary: mongod
version: 3.4.7
storage: wiredTiger # 获取12月11号凌晨开始语句的执行次数、用时等统计信息
[root@MONGO-17 logs]# mlogfilter shard.log --from 2017-12-11 0:00 > /tmp/121100.log
[root@MONGO-17 tmp]# mloginfo 121100.log --queries > /tmp/queries.txt
[root@MONGO-17 tmp]# head -n 20 queries.txt

2、分析mongodb统计数据

2.1 monogtop 统计信息

[root@MONGO-17 tmp]# /opt/mongodb/bin/mongotop -h 127.0.0.1:22001 -udbadmin -pxxx --authenticationDatabase=admin
2017-12-14T11:30:39.461+0800 Failed: error connecting to db server: server returned error on SASL authentication step: Authentication failed.

该用户无法在admin库下认证成功,当前只对mongos开启了认证

2.2 mongostat统计信息



2.3 mongodb 状态查看

[root@MONGO-16 ~]# echo 'db.serverStatus().connections' | /opt/mongodb/bin/mongo 127.0.0.1:27017/admin -udbadmin -puRqVxwYflphBgOH
MongoDB shell version v3.4.7
connecting to: mongodb://127.0.0.1:27017/admin
MongoDB server version: 3.4.7
{ "current" : 1564, "available" : 50864, "totalCreated" : 116536 }

三、扩展信息

  • mongotop可以查看MongoDB实例花销在读数据或写数据上的时间,它提供集合级别的统计数据
  • mongostat是提供数据库级别的统计数据

四、建议

  • 由分析mongodb的shard日志,omdmain.item_region、stock.region_product_inventory、order.order集合find操作关键字:IXSCAN,走不合理的索引以及执行count操作时间过长导致CPU飙高的主要原因。
  • 建议调整索引继续观察

排查MongoDB CPU使用率高的问题的更多相关文章

  1. MongoDB优化之三:如何排查MongoDB CPU利用率高的问题

    遇到这个问题,99.9999% 的可能性是「用户使用上不合理导致」,本文主要介绍从应用的角度如何排查 MongoDB CPU 利用率高的问题. Step1: 分析数据库正在执行的请求 用户可以通过 M ...

  2. Java进程CPU使用率高排查

    Java进程CPU使用率高排查 生产java应用,CPU使用率一直很高,经常达到100%,通过以下步骤完美解决,分享一下.1.jps 获取Java进程的PID.2.jstack pid >> ...

  3. MySQL CPU 使用率高的原因和解决方法

    用户在使用 MySQL 实例时,会遇到 CPU 使用率过高甚至达到 100% 的情况.本文将介绍造成该状况的常见原因以及解决方法,并通过 CPU 使用率为 100% 的典型场景,来分析引起该状况的原因 ...

  4. 服务器CPU使用率高的原因分析与解决办法

    我们的服务器在使用操作系统的时候,用着用着系统就变慢了,打开“ 任务管理器 ”一看,才发现CPU使用率达到80%以上.这是怎么回事情呢?遇到病毒了吗?硬件有问题?还是系统设置有问题呢?在本文中将从硬件 ...

  5. (原创)性能测试中,Oracle服务器定位CPU使用率高的瓶颈(SQL)

    本篇博客记录一次性能测试过程中,定位对CPU使用率高的瓶颈问题,主要定位SQL为准 一.用SQL命令定位1.首先用TOP命令监控系统资源,如果是AIX系统,就用topas,进入TOP命令的滚动刷新数据 ...

  6. 查询执行成本高(查询访问表数据行数多)而导致实例 CPU 使用率高是 MySQL 非常常见的问题

    MySQL CPU 使用率高的原因和解决方法_产品性能_常见问题_云数据库 RDS 版-阿里云 https://help.aliyun.com/knowledge_detail/51587.html ...

  7. JVM 线上故障排查基本操作--CPU飙高

    JVM 线上故障排查基本操作 CPU 飚高 线上 CPU 飚高问题大家应该都遇到过,那么如何定位问题呢? 思路:首先找到 CPU 飚高的那个 Java 进程,因为你的服务器会有多个 JVM 进程.然后 ...

  8. 交换机CPU使用率高的原因

    交换机CPU的功能 1.管理已配置的软件协议,例如: – 生成树协议(STP) – 路由协议,例如OSPF和EIGRP – 热备路由协议(HSRP) – 思科发现协议(CDP) – 端口聚合协议(PA ...

  9. 寻找CPU使用率高的进程方法

    寻找CPU使用率高的进程方法 发布时间:  2017-07-13 浏览次数:  1362 下载次数:  0 问题描述 节点报CPU使用率高,甚至出现"ALM-12016 CPU使用率超过阈值 ...

随机推荐

  1. @PostConstruct和@PreDestroy注解

    从Java EE5规范开始,Servlet增加了两个影响Servlet生命周期的注解(Annotation):@PostConstruct和@PreConstruct.这两个注解被用来修饰一个非静态的 ...

  2. Marshal.PtrToStringAnsi中文乱码

    出错代码: string dec = Marshal.PtrToStringAnsi(audioOutput.psz_description);//输出 鎵0鍣?(Realtek High Defi ...

  3. 关于 git 本地创建 SSH Key 遇到的一点问题(①file to save the key & ②the authenticity of host...)

    背景 由于想测试一下 SSH Key 创建的路径(.ssh 目录路径)对于不同位置 git 项目是否有效. 比如,.ssh 默认在 C:\[users]\[username] 目录下,而项目 proj ...

  4. Groovy Closure简介

    什么是闭包(Closure) 在Groovy中,闭包是一段匿名的代码段,它可以有参数,返回值,并且能够赋值给一个变量.闭包中使用的变量可以是在闭包外部定义的,也可以是在闭包内部定义的.

  5. anacoda报错No module named 'sklearn.cross_validation'

    在目前的snacoda里集成的sklearn已经不存在cross_validation模块了 使用以下模块 from  sklearn.model_selection  import train_te ...

  6. Java遍历Map对象的四种方式

    关于java中遍历map具体哪四种方式,请看下文详解吧. 方式一 :这是最常见的并且在大多数情况下也是最可取的遍历方式.在键值都需要时使用. Map<Integer, Integer> m ...

  7. js 实现控制点击事件在特定的毫秒内 只允许点击一次(防止重复点击)

    代码 第一种方法 var forbidRepeartClick = (function(){ var instance = null; var canClick = true; function Bu ...

  8. HTTP协议详解及http1.0与http1.1http2.0的区别

    HTTP协议介绍 http(超文本传输协议)是一个属于应用层的面向对象的协议,由于其简捷.快速的方式,适用于分布式超媒体信息系统.特点: (1)支持客户/服务器模式. HTTP是一个客户端和服务器端请 ...

  9. CentOS 7 配置静态IP后不生效 & Job for network.service failed

    参考:http://tieba.baidu.com/p/3233996339#57290767555l 在CentOS中配置静态IP后不生效. 解决办法:将/etc/sysconfig/network ...

  10. 【Idea】好的插件集合,持续更新

    UploadJar,用于配合Nexus上传jar包,方便上传 Key Promoter X,用于显示快捷键,学习快捷键非常实用 lombok,getter/setter使用注解,而不需要写 自动生成g ...