MongoDB執行個體的CPU使用率是一個非常重要的監控指標。如果MongoDB執行個體的CPU使用率過高,會導致MongoDB響應緩慢,甚至業務不可用。本文介紹查看MongoDB執行個體CPU使用率的方法,以及導致CPU使用率高的原因和最佳化策略。
查看方法
監控圖查看:在MongoDB管理主控台的監控資訊頁面,可以查看ApsaraDB for MongoDB的CPU使用率。關於採集粒度和操作步驟的更多資訊,請參見基本監控。
ApsaraDB for MongoDB不同架構的節點構成不同,您可以選擇對應節點,查看其CPU使⽤率。
複本集架構。包括一個主節點(Primary節點)、一個或多個從節點(Secondary節點)、一個隱藏節點(Hidden節點)和可選的一個或多個唯讀節點(ReadOnly節點)。
分區叢集架構。各個分區(Shard)的CPU使用與複本集保持一致;ConfigServer僅儲存配置中繼資料,基本上不會造成CPU瓶頸,一般可以忽略;Mongos路由節點的CPU使用往往與彙總結果集、並發請求數有關。
CPU使用率與執行個體規格有關,例如執行個體規格是8核16 GB,CPU使用率顯示100%時,表示該執行個體已經用滿了8核的CPU,而並非顯示800%。
常見原因
掃描行數過多
MongoDB為多線程應用,如果存在單個查詢掃描行數過多,該查詢所線上程的CPU佔用時間會變長,當請求堆積或此類查詢的並發度足夠高時,整個MongoDB執行個體的CPU佔用就會過高。從某種意義上說,MongoDB的CPU使用率與該執行個體的總掃描行數成正相關的關係。導致查詢掃描行數過多的情境有以下幾個方面:
全表掃描
當您在慢日誌或者 system.profile集合(需主動開啟database profiler)中發現
COLLSCAN關鍵字時,就表示該查詢進行了全表掃描。關於查看慢日誌與database profiler的更多資訊,請參見慢日誌。關於查詢執行計畫的更多解讀資訊,請參見:Explain Results和Cursor Methods。
不合理的索引設計與使用
當查詢的
docsExamined(文檔掃描條數)關鍵字超過1000且執行頻率較高時,需關注對應查詢。除全表掃描外,其他導致docsExamined過多的情況如下:多條件過濾時,未使用複合式索引或不滿足首碼匹配原則。
查詢過於複雜,或者存在⼤量的彙總類操作,基本⽆法從索引層⾯做到極致最佳化,或者導致查詢⾛錯解析計劃。
資料列的資料選擇性和運行頻率的評估錯誤,未能做到最好的折中。
並發過大
業務請求量過⼤,並發過⾼也會導致CPU佔用高。針對此問題,如果確認查詢層面沒有問題,一般通過添加CPU核心數的⽅式解決。
其他原因
頻繁短串連。MongoDB 3.X後使用的預設的身份認證機制是SCRAM-SHA1,需要進⾏⼀些CPU密集型操作,⽐如雜湊計算等。在⾼並發的短串連情境下,這些雜湊計算占⽤的CPU將會被放⼤很多倍,進⽽耗盡整個機器的CPU資源。其中⼀個現象是在運⾏⽇志中可以發現⼤量包含saslStart的報錯資訊。阿⾥雲MongoDB在PHP⾼並發短串連情境做了⼀定程度的最佳化,通過在核心層⾯最佳化改寫內建的隨機函數的⽅式⼤幅降低了MongoDB執行個體CPU使⽤率。
TTL索引導致從節點(Secondary)CPU使用率高於主節點(Primary)CPU使用率。如果遇到這種情況,建議您直接忽略。
自MongoDB 3.2開始實現了多線程複製,Oplog日誌的回放並發度由參數replWriterThreadCount控制,預設為16。所以儘管Secondary節點不承載任何業務寫,在部分情境下CPU使⽤率也可能會超過Primary節點。例如,在Primary節點上針對某⼀張表設定了TTL到期⾃動刪除,在Primary節點上,系統會根據時間列的索引大量刪除資料,效率很⾼,同時會將該操作轉換成很多單條的Delete操作發送給Secondary節點;在Secondary節點上,回放Oplog日誌時效率較低,所以在多線程回放的情況下容易引起該節點CPU升⾼。
排查方法
查看和Kill活躍會話
正常運行中的MongoDB執行個體會話突然飆升至100%,絕⼤部分情況是業務側的變化引起,可能是由於掃描行數過多、資料排序和彙總、業務流量突增等原因導致的。您可以通過以下方法排查:
在MongoDB管理主控台的頁面查看當前執行的活躍會話。分析不符合預期執行時間的查詢操作,可以選擇Kill活躍會話或者其他方法解決該問題。
通過MongoDB⾃帶的命令db.currentOp()查看和分析更加詳細的活躍會話執行情況。如果需要,可以通過命令db.killOp()主動Kill⾮預期內的慢查詢。詳情請參見db.currentOp()和db.killOp()。
記錄和查看日誌
當CPU使用率異常上升時,可以通過慢日誌或審計日誌深入分析異常請求。通過檢查COLLSCAN、docsExamined等關鍵字,進一步確認是否存在掃描行數過多的情況。
審計日誌
在MongoDB管理主控台的頁面開通並查看審計⽇志。關於審計⽇志的開通與使用方法,請參見開通日誌審計功能。
慢日誌
重要您只能查看7天內的慢日誌。
2021年06月06日後新購買的執行個體,需要先開通審計日誌功能,並設定需要審計的操作類型包含admin和slow,然後查看慢日誌。只能查看審計日誌功能開通之後出現的慢日誌。
在MongoDB管理主控台的頁面,根據業務需求設定operationProfiling.mode(慢查詢的模式)和operationProfiling.slowOpThresholdMs(慢查詢的閾值)。
MongoDB在profiling上共有3種設定模式:
關閉profiling,即不記錄任何請求。
針對所有請求開啟profiling,即將所有請求的執⾏都記錄到system.profile集合。
慢查詢profiling,將超過⼀定閾值的請求,記錄到system.profile集合。
關於profiling相關參數含義及更多資訊,請參見:Database Profiler。
在中查看慢日誌。
最佳化策略
最佳化索引
索引最佳化是減少MongoDB單個查詢掃描行數的最優⽅案。從底層設計上,MongoDB的索引設計原理幾乎與MySQL保持一致(或許種類和功能更豐富一些),所以適用於MySQL的索引最佳化策略基本也都適用於 MongoDB執行個體。
關於索引的建立與使用方式,請參見ApsaraDB for MongoDB建立索引最佳實務,或以下官方文檔:
複合式索引的原理和使⽤⽅法,詳情請參見:Compound Indexes。
使⽤索引排序,詳情請參見:Use Indexes to Sort Query Results。
使⽤Hint固化執⾏計劃,詳情請參考:Cursor Methods和cursor.hint()。
索引的資料選擇性和運⾏頻率折中⽅法,詳情請參見:Create Queries that Ensure Selectivity。
添加CPU核心數
如果確認查詢層⾯沒有問題,CPU佔用高是由於業務請求量過⼤、並發過⾼所導致,可以通過添加CPU核心數的⽅式解決。⼀般有如下⽅法:
單一實例垂直配置升降級,使得單一實例能夠承載更多的讀寫量。
配置複本集層面的讀寫分離,或者添加該副本的唯讀執行個體。
升級至MongoDB分區叢集,通過資料水平分割的方式橫向,線性擴充系統效能。
如果是Mongos路由節點CPU佔滿,則直接添加Mongos節點個數並設定Mongos節點的負載平衡,關於Mongos節點負載平衡的說明,請參見負載平衡。
ApsaraDB for MongoDB配置變更的更多資訊,請參見變更單節點執行個體配置、變更複本集執行個體配置和變更分區叢集執行個體配置。
控製表的數量和執行頻率
針對全表掃描的問題,優先通過添加索引的方式最佳化,如果已無法通過此方式最佳化,建議在業務側控製表的資料量和執行頻率。
避免頻繁短串連
建議您儘可能使⽤⻓串連。