ApsaraDB for MongoDB的記憶體使用量率是一個非常重要的監控指標。本文介紹查看ApsaraDB for MongoDB執行個體記憶體使用量率的方法,以及導致記憶體使用量率高的原因和最佳化策略。
背景資訊
ApsaraDB for MongoDB進程啟動後,不僅會載入二進位檔案和依賴的各種系統庫檔案到記憶體,而且負責記憶體的分配和釋放工作,例如用戶端的串連管理、請求處理和儲存引擎等。預設情況下,ApsaraDB for MongoDB的記憶體 Clerk是Google tcmalloc,記憶體主要被Wiredtiger儲存引擎和用戶端串連及請求處理佔用。
查看方法
分區叢集架構下,各個分區(Shard)的記憶體使用量與複本集架構保持一致,Config Server用於儲存配置中繼資料,Mongos路由節點的記憶體使用量率和彙總結果集、串連數大小、中繼資料大小相關。
複本集架構下,您可以通過以下方法查看記憶體的使用方式:
監控圖分析
ApsaraDB for MongoDB複本集由多種角色群組成,一個角色可能對應一個或多個物理節點。ApsaraDB for MongoDB複本集執行個體提供一個可供讀寫訪問的Primary節點(主節點)、一個或多個提供高可用的Secondary節點(從節點)、一個隱藏的Hidden節點(隱藏節點)和一個或多個可選的ReadOnly節點(唯讀節點)。
在MongoDB管理主控台的監控資訊頁面,可以查看ApsaraDB for MongoDB的記憶體使用量率。
命令列查看
在MongoDB Shell中使用
db.serverStatus().mem
命令查看和分析記憶體佔用情況,返回樣本如下:{ "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%,說明執行個體負載已經很高了。出於保護自身的目的,處理使用者請求的線程會主動參與到刷髒的工作中來,使用者側會明顯感覺到請求存在阻塞。具體規則,請參見 eviction參數說明。
您可以使用以下方法查看引擎記憶體的使用方式:
在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"), ...... }
在DAS控制台的效能趨勢頁面即時查看當前WiredTiger引擎的cache dirty比例。如何查看,請參見效能趨勢。
通過ApsaraDB for MongoDB內建的mongostat工具查看當前WiredTiger引擎的cache dirty比例。更多資訊,請參見mongostat。
串連和請求佔用的記憶體
如果執行個體的串連數很大,可能會消耗⼀部分的記憶體,原因如下:
每個串連,後端都有對應處理這個串連上的請求的線程。每個線程最多可以開銷1MB的線程棧,通常情況下在幾十KB~幾百KB。
每個TCP串連在核心層面有讀緩衝區和寫緩衝區,由TCP核心參數tcp_rmem和tcp_wmem等確定,這塊的記憶體使用量使用者無需關心。但並發串連越多,預設通訊端緩衝越大,則TCP佔用記憶體越大。
每接收到一個請求,會有個請求上下文,整個過程中可能分配很多臨時緩衝區,比如請求包、應答包和排序的臨時緩衝區等,這些在請求結束時都會釋放,但這個釋放只是歸還給記憶體 Clerk tcmalloc,tcmalloc優先會還到自己的cache裡,然後逐步再歸還給作業系統。
很多情況下,記憶體使用量率高的原因是tcmalloc未及時歸還記憶體⾄作業系統,這⼀塊最大可能達到幾十GB。關於tcmalloc未歸還OS的記憶體大小,可以通過命令
db.serverStatus().tcmalloc
查看。其中tcmalloc cache=pageheap_free_bytes+total_free_byte。返回資訊樣本如下:{ "generic":{ "current_allocated_bytes":NumberLong("9641570544"), "heap_size":NumberLong("19458379776") }, "tcmalloc":{ "pageheap_free_bytes":NumberLong("3048677376"), "pageheap_unmapped_bytes":NumberLong("544994184"), "current_total_thread_cache_bytes":95717224, "total_free_byte":NumberLong(1318185960), ...... } }
說明mongodb tcmalloc的更多資訊,請參見tcmalloc。
中繼資料資訊佔用的記憶體
ApsaraDB for MongoDB的資料庫、集合、索引等記憶體中繼資料等,如果集合和索引數量很多,這⼀塊佔用的記憶體也不容忽視。尤其在ApsaraDB for MongoDB4.0以前的版本,全量邏輯備份期間可能開啟非常多的⽂件控制代碼並且未能及時歸還OS導致記憶體快速上漲,或者低版本的ApsaraDB for MongoDB在大量刪除集合後可能未能刪除檔案控制代碼導致記憶體流失。
建立索引過程中的記憶體消耗
正常的業務資料寫⼊情況下,Secondary節點會維持⼀個最大約256M的buffer用於資料回放。在建立索引方面,當Primary節點建立索引完成後,Secondary節點回放過程中可能消耗更多的記憶體。在ApsaraDB for MongoDB4.2以前,在Primary節點上通過非background的⽅式建立索引,後端回放建立索引是串列的,最多可能消耗500M記憶體,而ApsaraDB for MongoDB4.2以後預設廢棄了background選項,允許Secondary節點並行回放建立索引,那就會消耗更多的記憶體,多個索引同時建立時可能導致執行個體記憶體溢出。
建立索引期間可能造成的記憶體消耗,詳情請參見index-build-impact-on-database-performance和index-build-process。
PlanCache記憶體佔用
在某些情境下,一個請求可能存在的執行計畫非常多,這時plancache會消耗比較多的記憶體。在高版本ApsaraDB for MongoDB中,您可以使用mgset-xxx:PRIMARY> db.serverStatus().metrics.query.planCacheTotalSizeEstimateBytes
命令查看PlanCache佔用的記憶體大小。更多資訊,請參見Secondary node memory arise while balancer doing work。
解決方案策略
記憶體最佳化並不是儘可能地減少記憶體使用量,而是在保證系統效能正常的前提下,記憶體足夠使用且穩定,在機器資源和效能中達到一個最佳的折衷。ApsaraDB for MongoDB協助使用者指定了CacheSize的大小,該值不支援修改。解決記憶體使用量的策略如下:
控制並發串連數。根據效能測試結果,資料庫中能夠建立100個長串連,預設MongoDB Driver可以和後端建立100個串連池。當存在很多用戶端時,就需要降低每個用戶端的串連池大小,一般建議與整個資料庫建立的長串連控制在1000以內,串連太多會導致記憶體和多線程內容相關的開銷增加,影響請求處理延時。
降低單次請求的記憶體開銷,例如通過建立索引減少集合的掃描、記憶體排序等。
在串連數合適的情況下記憶體佔用持續增高,建議升級記憶體配置,避免可能存在記憶體溢出和大量清除緩衝而導致系統效能急劇下滑。
加速tcmalloc釋放記憶體。如果您的資料庫執行個體記憶體使用量率超過80%,可以通過控制台的參數設定調整tcmalloc相關參數進行最佳化。優先開啟tcmallocAggressiveMemoryDecommit參數,因為此參數經過豐富的實踐驗證,對於解決記憶體相關問題有顯著效果。如果調整此參數後未達到預期效果,再考慮漸進式調大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。 |