全部產品
Search
文件中心

ApsaraDB for MongoDB:MongoDB執行個體記憶體使用量率高問題

更新時間:Dec 26, 2024

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"),
       ......
    }
  • 查看WiredTiger引擎的Cache Dirty比例

    • DAS控制台即時效能頁面即時查看當前WiredTiger引擎的Cache Dirty比例。如何查看,請參見即時效能

    • 通過ApsaraDB for MongoDB內建的mongostat工具查看當前WiredTiger引擎的Cache Dirty比例。更多資訊,請參見mongostat

串連和請求佔用的記憶體

如果執行個體的串連數很高,可能會消耗一部分的記憶體,原因如下:

  • 線程棧開銷。每個串連,後端都有對應處理這個串連上的請求的線程,每個線程最多可以開銷1MB的線程棧,通常情況下在幾十~幾百KB。

  • TCP串連核心緩衝區。每個TCP串連在核心層面有讀緩衝區和寫緩衝區,由TCP核心參數tcp_rmemtcp_wmem等確定,這塊的記憶體使用量使用者無需關心。但並發串連越多,預設通訊端緩衝越大,則TCP佔用記憶體越大。

  • tcmalloc記憶體管理。每接收到一個請求,會建立請求上下文並分配臨時緩衝區(如請求包、應答包和排序的臨時緩衝區等)。請求結束後,臨時緩衝區會釋放歸還給記憶體 Clerk tcmalloc,tcmalloc優先歸還到自己的緩衝裡,再逐步歸還至作業系統。很多情況下,記憶體使用量率高的原因是tcmalloc未及時歸還記憶體至作業系統,最多可達到幾十GB。

您可以使用以下方法排查:

  • 查看串連使用方式

  • 查看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-performanceindex-build-process

PlanCache記憶體佔用

在某些情境下,一個請求可能存在的執行計畫非常多,這時PlanCache會消耗比較多的記憶體。

查看PlanCache記憶體佔用大小:ApsaraDB for MongoDB 4.0及以上版本,可以通過db.serverStatus().metrics.query.planCacheTotalSizeEstimateBytes命令查看。

說明

最佳化策略

記憶體最佳化並不是儘可能地減少記憶體使用量,而是在保證系統效能正常的前提下,記憶體足夠使用且穩定,在機器資源和效能中達到一個最佳的折衷。

ApsaraDB for MongoDB協助使用者指定了CacheSize的大小,該值不支援修改。您可以使用以下策略進行記憶體最佳化:

  • 控制並發串連數。根據效能測試結果,資料庫中能夠建立100個長串連,預設MongoDB Driver可以和後端建立100個串連池。當存在很多用戶端時,就需要降低每個用戶端的串連池大小,一般建議與整個資料庫建立的長串連控制在1000以內,串連太多會導致記憶體和多線程內容相關的開銷增加,影響請求處理延時。

  • 降低單次請求的記憶體開銷。例如通過建立索引減少集合的掃描、記憶體排序等。

  • 升級記憶體配置。在串連數合適的情況下記憶體佔用持續增高,建議升級記憶體配置,避免可能存在記憶體溢出和大量清除緩衝而導致系統效能急劇下滑。

  • 加速tcmalloc釋放記憶體。如果您的資料庫執行個體記憶體使用量率超過80%,可以在控制台的參數設定頁面調整tcmalloc相關參數。

    1. 優先開啟tcmallocAggressiveMemoryDecommit參數。因為此參數經過豐富的實踐驗證,對於解決記憶體相關問題有顯著效果。

    2. 漸進式調大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,使用者線程也開始淘汰小對象相關的記憶體片段空間。