天天看點

MongoDB的性能問題之MongoDB 磁盤IO高問題

概述

阿裡雲資料庫MongoDB的IOPS使用率是一個非常重要的監控名額,IOPS使用率達到或接近100%後容易引起業務響應緩慢,甚至導緻業務不可用的情形。一般雲資料庫廠商為了避免主控端出現IO争搶,會使用Cgroup等技術進行執行個體間的IO隔離和IOPS限制,即不同規格的執行個體配置對應不同的IOPS使用上限。

本文将由淺入深幫您檢視、分析和優化雲資料庫MongoDB的IOPS使用率。

1 檢視IOPS使用

1.1 監控圖檢視

首先需要确認該執行個體的最大IOPS上限,通過點選"基本資訊"可以檢視,如下圖:

不同執行個體規格對應的IOPS使用上限參考:

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

通過點選"監控資訊"可以檢視到目前的IOPS使用量,因為絕大部分情況下阿裡雲資料庫MongoDB的data目錄和log目錄使用同一塊盤,是以IOPS使用量=data_iops=log_iops。

1.2 指令行檢視

在監控圖展示上,目前阿裡雲MongoDB僅限制IOPS,也僅展示IOPS的相關資訊。在實際的IO問題中,我們同樣可能需要關注IO吞吐量,IO延遲情況,通過db.serverStatus().systemInfo指令可以檢視IO相關的其他名額監控,不過所有監控項都是自MongoDB啟動以來的累加值,并不建議直接檢視。

如果使用者有自行開發更為詳細的MongoDB性能名額,可以基于上述指令的累加數值擷取更多的MongoDB IO名額。

2 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等,這些因素我們建議使用者根據實際業務需求情況設定即可,一般來說,不必為了盡可能地提高IO能力刻意修改。

關于更多Journal内容可參考:

https://docs.mongodb.com/manual/core/journaling/

關于更多WriteConcern内容可參考:

https://docs.mongodb.com/manual/reference/write-concern/

對于阿裡雲MongoDB來說,我們更推薦配置好合适的執行個體規格的同時,重點關注Index的優化和部分應用系統的寫入優化。

3 如何配置合适的執行個體規格

一般很難事先預估熱資料與CacheSize的比例設定為多少最合适,這是性能與執行個體費用的一個折衷。通用經驗下,我們建議在MongoDB執行個體在日常态運作過程中滿足業務RT要求的情況下,保證每日的峰值CPU使用率和IOPS使用率控制在50%以内。

4 Index優化

SQL全表掃描或者使用了不恰當的Index,比如導出全表資料期間,消耗的IO必然很大。另一方面,過多累贅的Index建立也會産生更多的資料規模,導緻WiredTiger Cache隻能緩存更小的熱資料,業務資料寫操作過程中也同樣多一次IO操作去更新Index,進而影響IO性能。

是以在避免濫用Index的情況下,需要為每個Query建立最合适的Index,關于這部分内容,可以參考:

https://docs.mongodb.com/manual/indexes/

5 業務架構和運維優化

在業務架構層面,要避免磁盤IO成為瓶頸,主要從以下幾個方面入手:

5.1 控制并發寫入/讀取線程數

MongoDB是多線程應用,但是我們并不推薦"極緻壓榨"MongoDB執行個體本身的性能,過高的并發寫入速度和複雜查詢并發數,容易引起IOPS瓶頸,甚至導緻Secondary節點持續延遲。具體的MongoDB IO壓力可以參考上文提到的mongostat中的dirty數值。

如果業務寫入量就是大到超出單機瓶頸,建議更新至MongoDB分片叢集模式,通過資料的水準拆分來線性擴容MongoDB的寫入性能。

5.2 盡可能避免峰值寫入

部分業務,比如日志系統的定期寫入或者遊戲系統中使用者資訊的批量持久化,容易造成一個一個IOPS峰值。針對這種情況,在目前的執行個體配置不足以支撐如此峰值寫入的情況下,我們建議業務側改造為平滑寫入,比如給每一個批量寫入操作添加一個随機時間片。

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

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

以上内容來自于《雲資料庫運維實戰手冊》電子書,可點選

https://developer.aliyun.com/topic/download?id=8198

下載下傳完整版,助力雲運維能力更上一層樓!