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