mongodb目前在业界的应用个别可分为两种架构:主从复制集和分片复制集集群。

因为分片复制集蕴含了主从复制集的性能,所以前面将以分片复制集为案例做阐明。

随同数据量的增长和业务压力的增大,常常有接管到mongodb分片集群的性能告警邮件。

我所保护的几套分片集群有时一天能收到200来封告警邮件,不胜其烦。告警邮件大抵分为三类:

  1. cpu 负载过高。cpu load average 值超过30,cpu 使用率超过50%。
  2. 闲暇内存不足,系统对swap 分区应用超过50%。
  3. IO 负载过高。IOwait 超过40%。

性能告警频繁,一线业务人员也不断反馈局部查问业务十分迟缓。有的平时失常状况执行很快的语句也变得十分慢。

以上种种性能问题如何解决呢。如何全面疾速的判断出零碎零碎性能瓶颈,而后给出相应的优化计划,让业务尽快安稳复原?

通过在理论生产中一直填坑后,总结出以下一些 mongodb性能问题诊断与优化的教训。

首先判断系统资源应用状况。

简略通过 top 命令可能迅速判断出零碎目前大抵的资源应用状况。

查看零碎cpu负载、io负载、内存应用状况等。有时不只是单纯的cpu 或者磁盘io或者内存吃紧一方面,

也有可能cpu、io,或者io、内存同时负载都很高。因而,咱们还须要借助性能监控工具做进一步深入分析。

mongodb 性能监控

通过mongostat 工具查看mongodb实例每秒读写数、执行命令、读写期待队列数、沉闷读写命令、网络吞吐、连接数等性能指标。

执行命令如下:

生产服务器主库30000端口,从库是30001端口。

/apps/svr/mongodb/bin/mongostat --host 127.0.0.1:30000 -uuser_name -p'password' --authenticationDatabase=admin

具体如下所示:

通过该性能监控工具至多能够理解mongodb实例整体连接数、读写申请数及读写比例(有的业务是读申请比重高,有的业务写申请比重较高)。

须要重点关注 qr|qw 读写期待队列数量。如果该值超过3或者超过cpu 核数,则代表cpu资源比拟吃紧,业务申请曾经开始积压。

通过 mongotop 查看mongodb 实例中热点表读写状况。

执行命令如下:

/apps/svr/mongodb/bin/mongotop --port 30000 -uuser_name -p'password' --authenticationDatabase=admin

该监控工具将依照申请工夫从大到小进行排序的前10个表的申请耗费工夫打印进去。

依据 二八定理,咱们能够抉择对于占用申请工夫超过80%的热表慢查问进行针对性的性能剖析和优化。

查看以后mongodb实例具体执行的慢查问申请。

例如,通过以下命令查看msg库以后大于3秒的慢查问。

db.currentOp({"active" : true,"secs_running" : { "$gt" : 3 },"ns" : /^msg/})

对于聚合剖析申请较多业务库,往往不断有超过100秒的聚合剖析语句正在执行。导致CPU和IO资源十分缓和。这时为了不影响失常业务的进行,只能临时抉择将很多沉积的慢查问语句先杀掉。

具体能够执行db.killOp("opid") 。opid为慢查问的惟一标识。

对于业务库慢SQL的查问与批量kill性能曾经在数据库治理平台雅典娜增加了。这里不再具体阐明。

以上两步咱们都是实时监控mongodb实例负载详情。如果当咱们开始处着手解决性能问题的时候零碎负载曾经恢复正常了,这该怎么办呢?这时就要借助zabbix 中记录的性能图进行剖析了。

刚好最近解决了一个美信音讯收发的mongodb集群的性能问题。

我残缺的讲一下问题解决流程。

  1. 首先,收到不少mongodb服务器cpu load 值很高的性能告警音讯。业务那边也反馈美信音讯收发很慢,甚至很多音讯都发不进来。

着手进行mongodb问题排查时,零碎负载又迅速掉下来。之前几天早上也陆续呈现几次相似的问题,然而没有如此重大。

  1. 查看zabbix 中 cpu 性能图。cpu load 值最高飙升到250。而且是从8:47到9:00这短短十几分钟就飙升下来了。继续不到10分钟cpu load 又开始急剧下降。

cpu load 为什么飙升这么高呢,根据教训判断。如果是长连贯的慢查问。cpu 使用率和load值增长和降落应该绝对安稳,没有如此急剧。

另外留神到的是,cpu资源剧增的时候,io和内存使用率比拟低。因而猜想是高并发的短平快申请数导致的cpu压力骤升。

同时也留神到,该分片集群单单是这个节点cpu负载分外高,其余两个节点服务器比拟失常。

为了剖析告警服务器在异样期间到底执行了什么工作,抉择用mtool工具对mongodb主节点实例进行具体的慢查问剖析。

mlogfilter 默认慢查问工夫是1000ms,因为后面剖析可能是短平快申请较多,所以这里设置慢查问工夫为300ms。

mlogfilter mongod30000.log --from '2018-11-14 08:45:01' --to '2018-11-14 09:10:00' --slow 300 > /tmp/msg31.log

查看慢查问详情并依照工夫耗费进行分类

mloginfo /tmp/msg31.log --queries --sort sum

如上图所示,慢查问响应工夫排名前八的全是update 写入操作。一些依据 _id 进行update,以及 msg-ios(8条记录)小表的update操作都十分慢,均匀执行工夫达到2~3秒。

失常状况下,这两种语句执行工夫都在100毫秒左右。因为写操作过于频繁,cpu load 值太高,失常的申请都被阻塞住。数据库整体响应都变得很慢。

mongodb 集群数据分布详情和分片键设置

该分片集群只是分片1节点cpu 负载特地高,因而初步狐疑热点表 im.msg_traces 分片数据分布也很不平均,热点数据集中在分片1上。查看了一下热表msg_traces 和 msg 的分片数据分布和分片键。都是以 _id 为hash 分片键,数据分布比拟平均。

这就有点困惑,三台物理机,唯独这台cpu load 分外高,数据盘 io %util 值也维持在90%左右。比照一下该节点与另外两台物理机的配置。发现型号和配置不一样。通过与虚拟机化那边共事确认。问题节点物理机IO吞吐比其余两台物理机的确要差一倍以上。

再次剖析分片1节点的慢查问日志。如下图所示,发现热表 msg_traces 上不少慢查问语句。

通过与开发共事沟通,热表 msg_traces、msg 上的查问和高并发update 语句都和公司美信音讯推送、查看、音讯状态批改等外围业务相干。业务上很难进行优化。因而,思考次要从以下四个方面进行 cpu/io 方面的优化解决:

1.集群架构上进行读写拆散。所有查问优先思考在从库上读取,写操作在主库上执行。防止主库混合读写压力过大,也缩小主库上读写记录的锁抵触。

connection string中readPreference 设置成secondarypreferred,C++ 驱动版本升级为3.1.3 mongo-cxx-driver(驱动降级,读写拆散才失效) 。

2.热表msg_traces 索引优化

针对该慢查问创立联结索引 {"_id": 1, "account": 1, "app_key": 1, "s_pc": 1}。

3.mongodb 历史数据归档和删除

和开发共事沟通,依据理论业务需要,保留msgs、msg_traces 汇合中一年左右的文档。在timestamp 字段上创立TTL索引。设置文档的过期工夫为 3153600秒(365243600)。

db.msgs.createIndex( { "timestamp ": 1 }, { expireAfterSeconds: 3153600 },{background: true} )

db.msg_traces.createIndex( { "timestamp ": 1 }, { expireAfterSeconds: 3153600 },{background: true} )

mongodb TTL索引将每隔60秒对过期数据执行一次删除操作。删除操作的继续理论取决于mongod 实例的负载。

4 .journal 日志的 commitIntervalMs 参数调整。

从默认的100ms调大到500ms。

目前通过读写拆散和索引优化之后,原来分片1在业务顶峰期间的cpu load 值由最高值250升高到5以内,优化成果非常明显。

mongodb 分片集群优化思路总结:

分片集群中呈现某个分片负载特地高的状况。(往往是某个分片负载高,如果是多个分片节点负载都高,则须要一一进行剖析)

第一步:

首先通过top、iostat、vmstat、mongostat 等工具理解零碎大抵并发负载和读写比例,察看零碎具体瓶颈所在。

第二步:

如果负载只是集中呈现在某一个节点上,则通过 mongotop 工具先剖析该mongodb实例的热点表是哪些并记录下来。

第三步:

通过 mlogfilter / mloginfo 工具剖析业务顶峰期间呈现的TOP10 慢查问。

第四步:

定位须要优化的指标表,并进行查问优化。

通常第二步和第三步会呈现很多雷同的表。因为热点数据表和慢查问表往往存在雷同的一些表。这些表就是咱们须要优化的指标。

mongodb 分片表的优化大抵从以下几方面着手:

1.查看表分片键、数据分布、数据总量、数据占用空间等信息。着重看数据分片键设置是否正当、数据分布是否平均;

2.mloginfo 工具打印进去的慢查问信息中有每个慢查问的查问条件。确认慢查问表上是否有适合的索引满足查问条件执行。须要联合explain() 剖析慢查问的具体执行打算。

3.选取业务顶峰阶段的mongodb实例原始日志,搜寻慢查问表相干的原始查问语句。记录这些原始查问语句,不便后续与开发共事沟通,看是否从业务场景上进行相应的优化。

4.对于日志、事件、会话信息等日志类型的表,能够依照业务需要,依据事件字段,只保留肯定工夫内的无效数据。通常这要与开发业务

沟通分明。确认保留工夫后,能够利用mongodb TTL索引个性,在特定工夫字段上创立索引,设置记录过期时限。

第五步:

架构上做读写拆散优化

如果在第三步找进去的 TOP10 慢查问不少是能无效利用索引的简略查问,失常状况下,执行应该很快(200ms之内)。

则须要思考在架构上做读写拆散的优化。因为热点表高并发的读写会让cpu 忙不过来,导致本来失常的查问都呈现阻塞。

总之,mongodb 优化要害之处是找出零碎瓶颈和问题本源。定位出须要优化的指标表后,简略地加个索引或者做个读写拆散,性能问题往往就迎刃而解。

这个和医生看病颇为类似,通过望闻问切和各种医疗测验设施所反馈的数据和报告,再根据丰盛的临床经验诊断出病因所在。找出病因后,开什么方子用什么药就是瓜熟蒂落的事了。当然,医生看病比给数据库做性能诊断简单多了,误诊几率也不小。而且,数据库性能优化没找准起因还有不少试错的机会,然而医生试错老本就比拟高了。所以当个好医生貌似比做个好DBA更难!

以上插了些题外话。优化上过程中,也须要和开发共事放弃无效沟通。当咱们了解慢查问产生的业务场景后,有时让开发共事配合做个简略的性能优化,头痛的性能问题也能随之解决。

关键词:前端培训