NC这一阵子MONGODB 的需求起来了,但问题是之前没来之前也用MONGODB 但实际得情况是,不怎么样。运维的同事告诉我,MONGODB 在公司原来的情况可以用一句话来表达,有这么个东西。
上礼拜MONGODB 一个复制集出现问题,报出在短短的5分钟出现 6亿的访问,然后应用就挂了,对我没写错 6亿,个人认为这6亿的确是有问题,可人家一堆人的反馈是就是MONGODB 有问题。这边不表到底我怎么解决的这个问题,这里先说说,遇到这样得问题,我们怎么办。
第一斧,快速了解你的MONGODB 所处的负载情况
1 打开你的MONGODB 的
mongostat --host 192.168.198.100:27027 -uroot -p1234.Com --authenticationDatabase admin
系统会打开当前的MONGODB 的监控实时的状态
其中可以查看当前mongodb在间隔时间中获取的insert update query delete command的数量以及当时的系统中的内存状态,脏页刷新的状态等等,网络的数据进出的状态,连接的数量等等。
mongostat --host 192.168.198.100:27027 -uroot -p1234.Com --authenticationDatabase admin --discover
在mongodb的使用中,我们几乎很少使用除复制集之外的模式,所以在我们连接到一个复制集中的机器后,可以在通过 --discover 来在一个界面上展示三台或更多的主机的在同一个时刻的情况。
在这些列表的数据中,我们需要注意
1 res 物理内存的使用量
2 faults 当faults 中的数字较大的情况,一般根据具体数据库承载的数据量和内存的情况,如果每秒访问数据都是出于失败的状态,说明内存不足。
3 qr 客户端等待读取数据的列长度
4 qw 客户等待数据写入的队列的长度
2 通过定期获得这些数据可以分析出系统的运行情况。
1 另外在一些情况下可以写一些脚本通过系统来获取一些MONGODB 的运行得数据
1.1 当前系统的连接情况,db.serverStatus().connections
这里的current 是标记当前的系统正在连接的数字,这里包含正在工作的和idel的连接。同时 available 不是MONGODB还能接受多少连接,而是LINUX 系统本身还能接受多少连接,具体还有多少连接与 配置中设置的MaxIncomingConnections 有关,具体还能有多少连接是通过 maxcomingConnections - current得出的数字,active 为当前活跃正在工作的连接数字。
第二斧, 针对当前访问数据库的源地址,进行分类,将每个地址对数据库访问进行统计
代码语言:javascript复制db.currentOp(true).inprog.reduce(
(accumulator, connection) => {
ipaddress = connection.client ? connection.client.split(":")[0] : "Internal";
accumulator[ipaddress] = (accumulator[ipaddress] || 0) 1;
accumulator["TOTAL_CONNECTION_COUNT"] ;
return accumulator;
},
{ TOTAL_CONNECTION_COUNT: 0 }
)
下面是一个更详细的展示方式
代码语言:javascript复制db.getSiblingDB("admin").aggregate( [
{ $currentOp: { allUsers: true, idleConnections: true, idleSessions: true } }
,{$project:{
"_id":0
,client:{$arrayElemAt:[ {$split:["$client",":"]}, 0 ] }
,curr_active:{$cond:[{$eq:["$active",true]},1,0]}
,curr_inactive:{$cond:[{$eq:["$active",false]},1,0]}
}
}
,{$match:{client:{$ne: null}}}
,{$group:{_id:"$client",curr_active:{$sum:"$curr_active"},curr_inactive:{$sum:"$curr_inactive"},total:{$sum:1}}}
,{$sort:{total:-1}}
] )
对当前的数据库服务器的内存的分配情况进行列出
db.serverStatus().tcmalloc.tcmalloc.formattedString
或者我们可以通过更简单的方式来展示,当前的Mongodb使用数据内存的方式。
db.serverStatus().mem
另外影响系统性能的另一个需要注意的地方就是mongodb中的锁,这里面我们需要注意三种锁
1 全局锁
2 数据库锁
3 collection 锁
db.serverStatus().locks.Global db.serverStatus().locks.Database db.serverStatus().locks.Collection
通过锁定期获取数字的变化,查看系统的性能的影响是否与锁有关。
第三斧, 对数据库中的执行的语句开启慢查询,获取慢查询的语句,不同于其他数据库,MONGODB 的慢查询本身并不是敞开的,主要还是因为我们对MONGODB 的慢查询的要求比较苛刻,基本上500ms的查询我们就要认为是慢查询需要进行查看如果不是聚合的话,是要进行优化的。
1 到对应要收集慢查询的数据库中,打开慢查询
db.setProfilingLevel(1,{slowms:500}) #打开慢查询 db.system.profile.find().pretty() #查看慢查询语句的记录 db.setProfilingLevel(0) 关闭慢查询 db.getProfilingLevel(0) 查看慢查询是否开启
db.system.profile.drop()
db.createCollection( "system.profile", { capped: true, size:4000000 } ) db.setProfilingLevel(1,{slowms:500}) db.getProfilingLevel()
如果是第二次或频繁打开慢查询,可以将上次的慢查询内容清空,然后在初始化慢查询collection ,在打开慢查询接受慢查询语句。
db.currentOp({"secs_running": {$gte: 5}})
或者直接在系统的currentOp中查看当前是否有慢的语句在执行。
在获得慢查询后,可以通过下面的语句针对不同时间段的慢查询信息,或者以满语句前10的方式来查询慢查询数据。
db.system.profile.find().limit(10).sort({ts:-1}).pretty()
db.system.profile.find( { ts : { $gt : new ISODate("2021-07-12T03:00:00Z") , $lt : new ISODate("2021-07-12T03:40:00Z") } }, { user : 0 } ).sort( { millis : -1 } )
基于MONGODB 本身的简单的特性,在快速处理MONGODB 的方法本身不用很多,只要能很快的命中问题的关键点,在加以分析,就能很快的找到问题的发生的点。