MongoDB內存佔用過大,最後OOM的解決辦法【記錄】

一、背景介紹

mongoDB喫內存,貌似已經是默認的現象了。而且現在內置存儲引擎也已經默認採用wiredTiger了。

最近有個測試,每秒1000多條數據的插入,應用側採用500個線程池進行插入,mongo屬於docker部署,只限制了wiredTiger的內存佔用,運行幾個小時後就會發現mongo發生OOM被殺死,查看運行log,最後有這麼幾條信息

2020-11-10T13:11:57.937050930Z {"t":{"$date":"2020-11-10T13:11:57.935+00:00"},"s":"E",  "c":"STORAGE",  "id":22435,   "ctx":"thread1010","msg":"WiredTiger error","attr":{"error":12,"message":"[1605013917:935682][1:0x7fe214b9b700], file:index-145-6498808884659112531.wt, eviction-server: __posix_file_write, 615: /data/db/index-145-6498808884659112531.wt: handle-write: pwrite: failed to write 12288 bytes at offset 90112: Cannot allocate memory"}}
2020-11-10T13:11:57.937126955Z {"t":{"$date":"2020-11-10T13:11:57.935+00:00"},"s":"E",  "c":"STORAGE",  "id":22435,   "ctx":"thread1010","msg":"WiredTiger error","attr":{"error":12,"message":"[1605013917:935887][1:0x7fe214b9b700], eviction-server: __wt_evict_thread_run, 327: cache eviction thread error: Cannot allocate memory"}}
2020-11-10T13:11:57.937140085Z {"t":{"$date":"2020-11-10T13:11:57.935+00:00"},"s":"E",  "c":"STORAGE",  "id":22435,   "ctx":"thread1010","msg":"WiredTiger error","attr":{"error":-31804,"message":"[1605013917:935926][1:0x7fe214b9b700], eviction-server: __wt_evict_thread_run, 327: the process must exit and restart: WT_PANIC: WiredTiger library panic"}}
2020-11-10T13:11:57.937147862Z {"t":{"$date":"2020-11-10T13:11:57.935+00:00"},"s":"F",  "c":"-",        "id":23089,   "ctx":"thread1010","msg":"Fatal assertion","attr":{"msgid":50853,"file":"src/mongo/db/storage/wiredtiger/wiredtiger_util.cpp","line":446}}
2020-11-10T13:11:57.937154249Z {"t":{"$date":"2020-11-10T13:11:57.936+00:00"},"s":"F",  "c":"-",        "id":23090,   "ctx":"thread1010","msg":"\n\n***aborting after fassert() failure\n\n"}
2020-11-10T13:11:57.937160477Z {"t":{"$date":"2020-11-10T13:11:57.936+00:00"},"s":"F",  "c":"CONTROL",  "id":4757800, "ctx":"thread1010","msg":"Writing fatal message","attr":{"message":"Got signal: 6 (Aborted).\n"}}

基本就是說內存無法分配的意思。

問題的大致方向清楚了,由於對這塊問題的思考不夠深入,沒辦法理解爲什麼內存會慢慢上升導致內存不夠用了,所以也百度了好久,最後換了谷歌纔算大概瞭解這個問題的原理。

這篇文章簡單講一下自己對mongoDB內存和CPU平衡的經過查閱所得出的一個思考

二、基礎知識

mongoDB傾向於內存操作,wiredTiger引擎,採用token來控制併發,同時採用eviction線程的機制來清理到達閾值的內存

三、分析

其實單從wiredTiger角度出發思考,內存佔用比作水池的話,上升的原因只可能是入大於出。入的話很簡單,就是我每秒1000多條的插入;出,根據基礎知識,則可能是因爲token數不夠,導致很多插入操作堆積、或者eviction的線程數不夠,對於內存的清理不夠及時。

問題原因挺簡單的,主要其實還是對於問題的認識,下面放一下谷歌到的參考鏈接,文章裏面也有參考鏈接,挺好的。

最後主要從cache,token(併發數),eviction(淘汰線程數)三個方面去實施。結果就是用CPU換內存。

這裏需要注意關於token併發數設置,需要將數字用雙引號應用

db.adminCommand({setParameter: 1, wiredTigerConcurrentWriteTransactions: “512”})
同時eviction策略相關設置目前沒有在官方文檔裏面看到,是不是默認的已經很好了,不提供修改選項了?
所以目前就從token和cache size方面進行了設置。
給大家一個參考的docker運行命令
docker run --name mongodb --cpus 1 -m 4G  -v /alidata/MongoData:/data/db -p 27017:27017 -d mongo:4.4.1
--wiredTigerCacheSizeGB 2.4 --setParameter wiredTigerConcurrentWriteTransactions=1500

四、結果

結果好壞,通過mongostat命令,主要觀察qrw一列看是否有堆積,然後內存佔用這個肯定是會上升的,主要看當時wiredTiger的cache大小設置,同時還有相關的mongo操作需要mongod佔用內存(這部分是剛需,基本避免不了吧)。

至於mongostat這個命令行工具結果中各列含義,則可以參照

https://docs.mongodb.com/v4.2/reference/program/mongostat/

最後結果如下圖

image

used一列一直在80%上下徘徊(mongodb默認的緩存清理時機,緩存佔用達到80%開始清理),沒有再出現OOM的問題,不過CPU佔用變高了

image

五、參考鏈接

https://caosiyang.github.io/posts/2016/08/23/mongodb-wiredtiger-performance-tuning/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章