【巡检问题分析与最佳实践】MongoDB 磁盘IO高问题

往期分享

RDS MySQL

RDS MySQL 实例空间问题

RDS MySQL 内存使用问题

RDS MySQL 活跃线程数高问题

RDS MySQL 慢SQL问题

RDS MySQL 实例IO高问题

RDS MySQL 小版本升级最佳实践

RDS PostgreSQL

RDS PostgreSQL 实例IO高问题

RDS PostgreSQL 慢SQL问题

RDS PostgreSQL CPU高问题

RDS SQL Server

RDS SQL Server 磁盘IO吞吐高问题

RDS SQL Server CPU高问题

RDS SQL Server 空间使用问题

Redis

Redis 流控问题

Redis 内存高问题

Redis CPU高问题

MongoDB

MongoDB 内存高问题

概述

阿里云数据库MongoDB的IOPS使用率是一个非常重要的监控指标,IOPS使用率达到或接近100%后容易引起业务响应缓慢,甚至导致业务不可用的情形。一般云数据库厂商为了避免宿主机出现IO争抢,会使用Cgroup等技术进行实例间的IO隔离和IOPS限制,即不同规格的实例配置对应不同的IOPS使用上限。

本文将由浅入深帮您查看、分析和优化云数据库MongoDB的IOPS使用率。

查看IOPS使用

监控图查看

首先需要确认该实例的最大IOPS上限,通过点击"基本信息"可以查看,如下图:

【巡检问题分析与最佳实践】MongoDB 磁盘IO高问题

不同实例规格对应的IOPS使用上限参考:

https://help.aliyun.com/document_detail/57141.html

通过点击"监控信息"可以查看到当前的IOPS使用量,因为绝大部分情况下阿里云数据库MongoDB的data目录和log目录使用同一块盘,所以IOPS使用量=data_iops=log_iops。

【巡检问题分析与最佳实践】MongoDB 磁盘IO高问题

命令行查看

在监控图展示上,目前阿里云MongoDB仅限制IOPS,也仅展示IOPS的相关信息。在实际的IO问题中,我们同样可能需要关注IO吞吐量,IO延迟情况,通过db.serverStatus().systemInfo命令可以查看IO相关的其他指标监控,不过所有监控项都是自MongoDB启动以来的累加值,并不建议直接查看。

如果用户有自行开发更为详细的MongoDB性能指标,可以基于上述命令的累加数值获取更多的MongoDB IO指标。

MongoDB 磁盘IO问题常见原因和优化策略

对于云数据库MongoDB来说,底层的磁盘硬件性能对用户透明,完全交由云厂商负责,用户只需要核心关注业务的正确使用MongoDB,以及配置合适的内存和IOPS上限。

通常来说,MongoDB的IO问题与内存的CacheSize大小息息相关。CacheSize越大,表示能够缓存的热数据越大,那么系统需要的磁盘IO量也就越低,出现IO瓶颈的概率越低;反之,CacheSize越小,表示能否缓存的热数据越少,系统刷脏也更频繁,实例出现IO压力的概率也就越大。

您可以通过mongostat或者阿里云数据库自治服务DAS实时查看当前的cache dirty,目前阿里云数据库MongoDB暂不支持cache dirty历史情况查看。如果出现 dirty>20%,并一直持续,说明内存淘汰压力很大,用户的请求线程会阻塞参与page淘汰,请求延时就会增加,这时可以考虑"扩大内存"或者"扩大IOPS"。

更多mongostat的使用方式可以参考:https://docs.mongodb.com/v4.2/reference/program/mongostat/

还有一些与磁盘IO相关的参数和配置,比如MongoDB Journal和运行日志刷盘,WriteConcern设置,分片集群的MoveChunk等,这些因素我们建议用户根据实际业务需【巡检问题分析与最佳实践】MongoDB 磁盘IO高问题求情况设置即可,一般来说,不必为了尽可能地提高IO能力刻意修改。

关于更多Journal内容可参考:https://docs.mongodb.com/manual/core/journaling/

关于更多WriteConcern内容可参考:https://docs.mongodb.com/manual/reference/write-concern/

对于阿里云MongoDB来说,我们更推荐配置好合适的实例规格的同时,重点关注Index的优化和部分应用系统的写入优化。

如何配置合适的实例规格

一般很难事先预估热数据与CacheSize的比例设置为多少最合适,这是性能与实例费用的一个折衷。通用经验下,我们建议在MongoDB实例在日常态运行过程中满足业务RT要求的情况下,保证每日的峰值CPU使用率和IOPS使用率控制在50%以内。

Index优化

SQL全表扫描或者使用了不恰当的Index,比如导出全表数据期间,消耗的IO必然很大。另一方面,过多累赘的Index创建也会产生更多的数据规模,导致WiredTiger Cache只能缓存更小的热数据,业务数据写操作过程中也同样多一次IO操作去更新Index,从而影响IO性能。

所以在避免滥用Index的情况下,需要为每个Query创建最合适的Index,关于这部分内容,可以参考:https://docs.mongodb.com/manual/indexes/

业务架构和运维优化

在业务架构层面,要避免磁盘IO成为瓶颈,主要从以下几个方面入手:

控制并发写入/读取线程数

MongoDB是多线程应用,但是我们并不推荐"极致压榨"MongoDB实例本身的性能,过高的并发写入速度和复杂查询并发数,容易引起IOPS瓶颈,甚至导致Secondary节点持续延迟。具体的MongoDB IO压力可以参考上文提到的mongostat中的dirty数值。

如果业务写入量就是大到超出单机瓶颈,建议升级至MongoDB分片集群模式,通过数据的水平拆分来线性扩容MongoDB的写入性能。

尽可能避免峰值写入

部分业务,比如日志系统的定期写入或者游戏系统中用户信息的批量持久化,容易造成一个一个IOPS峰值。针对这种情况,在当前的实例配置不足以支撑如此峰值写入的情况下,我们建议业务侧改造为平滑写入,比如给每一个批量写入操作添加一个随机时间片。

【巡检问题分析与最佳实践】MongoDB 磁盘IO高问题

避免业务高峰期间做运维操作

一些对性能影响较大的运维操作本质上也是认为造成了IOPS峰值,在无法避免的情况下,应该尽可能避免在业务高峰期执行。常见的容易引起IO高峰的运维操作有批量写入/更新/删除数据,添加Index,对集合执行Compact操作,批量导出数据等。





上一篇:【巡检问题分析与最佳实践】Redis CPU高问题


下一篇:【巡检问题分析与最佳实践】Redis内存高问题