MongoDB內存過高問題分析及解決
告警
公司有個3.2.7版本的mongo復制集,最近幾天頻繁告警內存過高。
服務器配置16C+64G內存。mongo備節(jié)點內存使用到55G,觸發(fā)告警。
以下內容基于3.2.7版本,3.2.7版本已經(jīng)太老,很多后來的命令和配置,3.2.7都沒有。
排查
排查mongo配置
主要是檢查cacheSizeGB
wiredTiger: engineConfig: cacheSizeGB: 20
MongoDB 3.2 及以后,默認使用 WiredTiger 存儲引擎,可通過 cacheSizeGB
選項配置 WiredTiger 引擎使用內存的上限,一般建議配置在系統(tǒng)可用內存的一班左右。
默認值是(RAM – 1GB) / 2。出發(fā)點是防止系統(tǒng)OOM kill。因為這里的配置只是wiredTiger的內存cache限額,并不是mongo的全部使用內存限額,整個mongo進程的內存占用要比這個值大,所以cacheSizeGB萬萬不可設置超過RAM的60%。
我們這里配置到了20G。但是實際運行中發(fā)現(xiàn),在并發(fā)查詢很高的情況下,wt的cacheSize還是會超過這個配置一點點。
查看mongo實例的內存使用情況
db.serverStatus().wiredTiger.cache
返回結果中 bytes currently in the cache 后的值為緩存數(shù)據(jù)的大小
... "bytes currently in the cache" : 21483838298, ...
已經(jīng)用滿了,這種情況可以加一下內存了。但是內存太貴,業(yè)務也沒有那么高的性能要求,保障不宕機是更有性價比的方案。
既然cache只用了20G,
看看tcmalloc的情況
db.serverStatus().tcmalloc
------------------------------------------------ MALLOC: 22351254936 (21315.8 MiB) Bytes in use by application MALLOC: + 24922800128 (23768.2 MiB) Bytes in page heap freelist MALLOC: + 449403872 ( 428.6 MiB) Bytes in central cache freelist MALLOC: + 262144 ( 0.2 MiB) Bytes in transfer cache freelist MALLOC: + 841870984 ( 802.9 MiB) Bytes in thread cache freelists MALLOC: + 109572256 ( 104.5 MiB) Bytes in malloc metadata MALLOC: ------------ MALLOC: = 48675164320 (46420.3 MiB) Actual memory used (physical + swap) MALLOC: + 8663441408 ( 8262.1 MiB) Bytes released to OS (aka unmapped) MALLOC: ------------ MALLOC: = 57338605728 (54682.4 MiB) Virtual address space used MALLOC: MALLOC: 378600 Spans in use MALLOC: 1451 Thread heaps in use MALLOC: 8192 Tcmalloc page size ------------------------------------------------ Call ReleaseFreeMemory() to release freelist memory to the OS (via madvise()). Bytes released to the OS take up virtual address space but no physical memory.
可以看到page heap freelist占了大頭。
解釋一下,57338605728 (54682.4 MiB) Virtual address space used 是mongo總的使用的虛擬內存。
48675164320 (46420.3 MiB) Actual memory used (physical + swap)是mongo總的使用的實際內存。(我沒有開swap)
實際內存又分成兩部分,freelist中的和非freelist的。freelist的就是已經(jīng)分配后來又用完釋放的內存,存在這個freelist數(shù)據(jù)結構中,已備后面重用這些內存,我的理解就是我用完了,但是我先拿著。這樣后面的業(yè)務來了,mongo就不需要再向os申請分配內存這一步了,從性能和效率的維度來看更好。
但是缺點是內存一直沒有還給os,導致os角度來看,內存的使用率很高。
tcmalloc 為性能考慮,每個線程會有自己的 local free page cache,還有 central free page cache;內存申請時,按 local thread free page cache ==> central free page cache 查找可用內存,找不到可用內存時才會從堆上申請;當釋放內存時,也會歸還到 cache 里,tcmalloc 后臺慢慢再歸還給 OS操作系統(tǒng), 多數(shù)情況下,內存使用率高的原因是 tcmalloc 未能及時將內存歸還給操作系統(tǒng),導致內存最大可能達到幾十GB。mongo為了提高性能,傾向于利用os上盡可能多的內存。
解決
所以可以將freelist的內存及時釋放給os,可以解決內存水位過高的問題。
db.adminCommand({setParameter:1,tcmallocAggressiveMemoryDecommit:1})
tcmallocAggressiveMemoryDecommit
是一個服務器參數(shù),用于控制 TCMalloc 內存分配器在什么程度上積極地將不再使用的內存釋放回操作系統(tǒng)。當設置為 1
(開啟狀態(tài))時,tcmallocAggressiveMemoryDecommit
會使 TCMalloc 更積極地釋放不再使用的內存。這意味著當應用程序釋放內存后,TCMalloc 會嘗試將這部分內存標記為空閑并返回給操作系統(tǒng),而不是保留在進程的地址空間中以便快速重用。
以上就是MongoDB內存過高問題分析及解決的詳細內容,更多關于MongoDB內存過高的資料請關注腳本之家其它相關文章!
相關文章
mongodb 修改器($inc/$set/$unset/$push/$pop/upsert)
對于文檔的更新除替換外,針對某個或多個文檔只需要部分更新可使用原子的更新修改器,能夠高效的進行文檔更新。更新修改器是中特殊的鍵2017-04-04MongoDB數(shù)據(jù)庫去重函數(shù)Distinct用法實例
在MongoDB中可以使用distinct()方法對變量進行去重操作,distinct()方法是用于返回指定字段的唯一值的操作,這篇文章主要給大家介紹了關于MongoDB數(shù)據(jù)庫去重函數(shù)Distinct用法的相關資料,需要的朋友可以參考下2024-06-06【MongoDB for Java】Java操作MongoDB數(shù)據(jù)庫
本篇文章現(xiàn)在我們就用Java來操作MongoDB的數(shù)據(jù)。小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-12-12Windows10安裝MongoDB4.0詳細步驟及啟動配置教程
這篇文章主要介紹了Windows10安裝MongoDB4.0詳細步驟及啟動配置教程 ,本文通過圖文并茂的形式給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2020-01-01