開發與維運

【巡檢問題分析與最佳實踐】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上限,通過點擊"基本信息"可以查看,如下圖:

image.png

不同實例規格對應的IOPS使用上限參考:

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

通過點擊"監控信息"可以查看到當前的IOPS使用量,因為絕大部分情況下阿里雲數據庫MongoDB的data目錄和log目錄使用同一塊盤,所以IOPS使用量=data_iops=log_iops。

image.png

命令行查看

在監控圖展示上,目前阿里雲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"。image

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

還有一些與磁盤IO相關的參數和配置,比如MongoDB Journal和運行日誌刷盤,WriteConcern設置,分片集群的MoveChunk等,這些因素我們建議用戶根據實際業務需求情況設置即可,一般來說,不必為了儘可能地提高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峰值。針對這種情況,在當前的實例配置不足以支撐如此峰值寫入的情況下,我們建議業務側改造為平滑寫入,比如給每一個批量寫入操作添加一個隨機時間片。

image.png

避免業務高峰期間做運維操作

一些對性能影響較大的運維操作本質上也是認為造成了IOPS峰值,在無法避免的情況下,應該儘可能避免在業務高峰期執行。常見的容易引起IO高峰的運維操作有批量寫入/更新/刪除數據,添加Index,對集合執行Compact操作,批量導出數據等。

Leave a Reply

Your email address will not be published. Required fields are marked *