ApsaraDB for MongoDB的記憶體使用量率是一個非常重要的監控指標。本文介紹查看ApsaraDB for MongoDB執行個體記憶體使用量率的方法,以及導致記憶體使用量率高的原因和最佳化策略。
背景資訊
ApsaraDB for MongoDB進程啟動後,不僅會載入二進位檔案和依賴的各種系統庫檔案到記憶體,而且負責記憶體的分配和釋放工作,例如用戶端的串連管理、請求處理和儲存引擎等。預設情況下,ApsaraDB for MongoDB的記憶體 Clerk是Google tcmalloc,記憶體主要被Wiredtiger儲存引擎和用戶端串連及請求處理佔用。
查看方法
監控圖分析
在MongoDB管理主控台的監控資訊頁面,可以查看ApsaraDB for MongoDB的記憶體使用量率。ApsaraDB for MongoDB不同架構的節點構成不同,您可以選擇對應節點,查看其記憶體使用量率。
複本集架構。包括一個主節點(Primary節點)、一個或多個從節點(Secondary節點)、一個隱藏節點(Hidden節點)和可選的一個或多個唯讀節點(ReadOnly節點)。
分區叢集架構。各個分區(Shard)的記憶體使用量與複本集架構一致,Config Server用於儲存配置中繼資料,Mongos路由節點的記憶體使用量率和彙總結果集、串連數大小、中繼資料大小相關。
命令列查看
通過在MongoDB Shell中使用
db.serverStatus().mem
命令查看和分析記憶體佔用情況。MongoDB Shell串連方法,請參見串連MongoDB。返回樣本如下:
{ "bits" : 64, "resident" : 13116, "virtual" : 20706, "supported" : true }
// resident 表示該mongod物理節點佔用的實體記憶體大小,單位為MB。
// virtual 表示該mongod物理節點佔用的虛擬記憶體大小,單位為MB。
關於serverStatus的更多資訊,請參見serverStatus。
常見原因
引擎記憶體
ApsaraDB for MongoDB的大部分記憶體都會用於儲存引擎緩衝。考慮到相容性和安全性,ApsaraDB for MongoDB將儲存引擎WiredTiger的CacheSize設定為實際申請的執行個體記憶體規格大小的60%左右。具體規格,請參見產品規格。
如果儲存引擎緩衝使用了CacheSize配置大小的95%,說明執行個體負載已經很高,處理使用者請求的線程會參與淘汰CLEAN PAGE。如果儲存引擎髒資料緩衝佔比超過20%,使用者線程會參與淘汰DIRTY PAGE。在此過程中,使用者側會明顯感覺到請求存在阻塞。具體規則,請參見 eviction參數說明。
您可以使用以下方法查看引擎記憶體的使用方式:
查看WiredTiger引擎的記憶體佔用大小
在MongoDB Shell中通過
db.serverStatus().wiredTiger.cache
查看。返回資訊中bytes currently in the cache
後的值為記憶體大小。返回資訊樣本如下:{ ...... "bytes belonging to page images in the cache":6511653424, "bytes belonging to the cache overflow table in the cache":65289, "bytes currently in the cache":8563140208, "bytes dirty in the cache cumulative":NumberLong("369249096605399"), ...... }
串連和請求佔用的記憶體
如果執行個體的串連數很高,可能會消耗一部分的記憶體,原因如下:
線程棧開銷。每個串連,後端都有對應處理這個串連上的請求的線程,每個線程最多可以開銷1MB的線程棧,通常情況下在幾十~幾百KB。
TCP串連核心緩衝區。每個TCP串連在核心層面有讀緩衝區和寫緩衝區,由TCP核心參數tcp_rmem和tcp_wmem等確定,這塊的記憶體使用量使用者無需關心。但並發串連越多,預設通訊端緩衝越大,則TCP佔用記憶體越大。
tcmalloc記憶體管理。每接收到一個請求,會建立請求上下文並分配臨時緩衝區(如請求包、應答包和排序的臨時緩衝區等)。請求結束後,臨時緩衝區會釋放歸還給記憶體 Clerk tcmalloc,tcmalloc優先歸還到自己的緩衝裡,再逐步歸還至作業系統。很多情況下,記憶體使用量率高的原因是tcmalloc未及時歸還記憶體至作業系統,最多可達到幾十GB。
您可以使用以下方法排查:
查看串連使用方式
在MongoDB管理主控台的監控資訊頁面,可以查看ApsaraDB for MongoDB的串連使用方式。
通過Mongo Shell查詢串連數。具體方法,請參見如何查詢及限制串連數。
查看tcmalloc未歸還作業系統的記憶體大小
通過
db.serverStatus().tcmalloc
命令查看tcmalloc未歸還作業系統的記憶體大小。其中tcmalloc cache=pageheap_free_bytes+total_free_byte。返回樣本如下:{ ...... "tcmalloc":{ "pageheap_free_bytes":NumberLong("3048677376"), "pageheap_unmapped_bytes":NumberLong("544994184"), "current_total_thread_cache_bytes":95717224, "total_free_byte":NumberLong(1318185960), ...... } }
說明tcmalloc的更多資訊,請參見tcmalloc。
中繼資料資訊佔用的記憶體
ApsaraDB for MongoDB的資料庫、集合、索引等記憶體中繼資料,數量很多時將佔用較多的記憶體。低版本的ApsaraDB for MongoDB,可能存在以下問題:
ApsaraDB for MongoDB 4.0以下版本,全量邏輯備份期間可能開啟非常多的檔案控制代碼,如果未及時歸還作業系統,將導致記憶體快速上漲。
ApsaraDB for MongoDB 4.0及以下版本在大量刪除集合後,可能未能刪除檔案控制代碼,將導致記憶體流失。
建立索引過程中的記憶體消耗
正常資料寫入時,Secondary節點會維持一個最大約256M的buffer用於資料回放。在建立索引方面,Secondary節點回放過程中可能消耗更多的記憶體。
ApsaraDB for MongoDB 4.2以下版本,建立索引支援
background
選項。當指定{background:true}
時,進行後台建立,回放建立索引是串列的,最多可能消耗500M記憶體。ApsaraDB for MongoDB 4.2及以上版本預設廢棄了
background
選項。允許Secondary節點並行回放建立索引,會消耗更多的記憶體,多個索引同時建立時可能導致執行個體記憶體溢出。
建立索引期間可能造成的記憶體消耗,詳情請參見index-build-impact-on-database-performance和index-build-process。
PlanCache記憶體佔用
在某些情境下,一個請求可能存在的執行計畫非常多,這時PlanCache會消耗比較多的記憶體。
查看PlanCache記憶體佔用大小:ApsaraDB for MongoDB 4.0及以上版本,可以通過db.serverStatus().metrics.query.planCacheTotalSizeEstimateBytes
命令查看。
如果您的執行個體為ApsaraDB for MongoDB 4.0版本,但執行上述命令時沒有相關欄位,說明執行個體小版本太低,建議升級小版本。具體操作,請參見升級資料庫小版本。
PlanCache記憶體佔用的更多資訊,請參見Secondary node memory arise while balancer doing work。
最佳化策略
記憶體最佳化並不是儘可能地減少記憶體使用量,而是在保證系統效能正常的前提下,記憶體足夠使用且穩定,在機器資源和效能中達到一個最佳的折衷。
ApsaraDB for MongoDB協助使用者指定了CacheSize的大小,該值不支援修改。您可以使用以下策略進行記憶體最佳化:
控制並發串連數。根據效能測試結果,資料庫中能夠建立100個長串連,預設MongoDB Driver可以和後端建立100個串連池。當存在很多用戶端時,就需要降低每個用戶端的串連池大小,一般建議與整個資料庫建立的長串連控制在1000以內,串連太多會導致記憶體和多線程內容相關的開銷增加,影響請求處理延時。
降低單次請求的記憶體開銷。例如通過建立索引減少集合的掃描、記憶體排序等。
升級記憶體配置。在串連數合適的情況下記憶體佔用持續增高,建議升級記憶體配置,避免可能存在記憶體溢出和大量清除緩衝而導致系統效能急劇下滑。
加速tcmalloc釋放記憶體。如果您的資料庫執行個體記憶體使用量率超過80%,可以在控制台的參數設定頁面調整tcmalloc相關參數。
優先開啟tcmallocAggressiveMemoryDecommit參數。因為此參數經過豐富的實踐驗證,對於解決記憶體相關問題有顯著效果。
漸進式調大tcmallocReleaseRate參數值。如果調整上述參數後未達預期,再漸進式調大tcmallocReleaseRate參數值,例如從1調整到3,再到5。
重要建議在業務低峰期調整。tcmallocAggressiveMemoryDecommit和tcmallocReleaseRate參數調整可能會導致資料庫效能退化,業務受到影響後請及時復原。
最佳化庫表數量。如果資料庫執行個體存在過多的庫表,可以移除不需要的集合、索引,整合多表資料,拆分執行個體,或者遷移到分區叢集等。具體操作,請參見庫表數太多導致執行個體卡頓或異常。
如果您在使用ApsaraDB for MongoDB過程中遇到更多可能存在記憶體流失的情境,可以聯絡阿里雲技術⽀持處理。
參考
eviction參數說明
參數 | 預設值 | 含義 |
eviction_target | 80% | 當cache used超過eviction_target,後台evict線程開始淘汰CLEAN PAGE。 |
eviction_trigger | 95% | 當cache used超過eviction_trigger,使用者線程也開始淘汰CLEAN PAGE。 |
eviction_dirty_target | 5% | 當cache dirty超過eviction_dirty_target,後台evict線程開始淘汰DIRTY PAGE。 |
eviction_dirty_trigger | 20% | 當cache dirty超過eviction_dirty_trigger,使用者線程也開始淘汰DIRTY PAGE。 |
eviction_updates_target | 2.5% | 當cache update ratio超過eviction_updates_target,後台evict線程開始淘汰小對象相關的記憶體片段空間。 |
eviction_updates_trigger | 10% | 當cache update ratio超過eviction_updates_trigger,使用者線程也開始淘汰小對象相關的記憶體片段空間。 |