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