Mongodb

MongoDB 使用太多記憶體

  • February 25, 2021

我們已經使用 MongoDB 幾個星期了,我們看到的總體趨勢是 mongodb 使用了太多的記憶體(遠遠超過其數據集 + 索引的整體大小)。

我已經通讀了這個問題這個問題,但似乎都沒有解決我一直面臨的問題,他們實際上是在解釋文件中已經解釋的內容。

以下是htopshow dbs命令的結果。

在此處輸入圖像描述

顯示數據庫

我知道 mongodb 使用記憶體映射 IO,所以基本上作業系統會處理記憶體中的記憶體內容,並且 mongodb理論上應該在另一個程序請求空閒記憶體時釋放它的記憶體記憶體,但從我們所看到的情況來看,它沒有。

OOM 開始殺死其他重要程序,例如 postgres、redis 等。(可以看出,為了克服這個問題,我們將 RAM 增加到 183GB,現在可以使用但非常昂貴。mongo 使用 ~87GB 的 ram,幾乎是整個數據集大小的 4 倍)

所以,

  1. 這麼多記憶體使用量真的是預期的和正常的嗎?(根據文件,WiredTiger 最多使用約 60% 的 RAM 作為其記憶體,但考慮到數據集的大小,它甚至有足夠的數據來佔用 86GB 的 RAM 嗎?)
  2. 即使記憶體使用量是預期的,如果另一個程序開始請求更多記憶體,為什麼 mongo 不會釋放其分配的記憶體?在我們增加 RAM 之前,Linux oom 會不斷殺死其他各種正在執行的程序,包括 mongodb 本身,這會使系統完全不穩定。

謝謝 !

好的,所以在遵循 loicmathieu 和 jstell 提供的線索,並對其進行了一點探勘之後,我發現了關於使用 WiredTiger 儲存引擎的 MongoDB 的一些事情。如果有人遇到相同的問題,我會把它放在這裡。

我提到的記憶體使用執行緒都屬於 2012-2014 年,都早於 WiredTiger,並且正在描述原始 MMAPV1 儲存引擎的行為,該引擎沒有單獨的記憶體或不支持壓縮。

WiredTiger記憶體設置只控制 WiredTiger 儲存引擎直接使用的記憶體大小(不是 mongod 使用的總記憶體)。在 MongoDB/WiredTiger 配置中,許多其他東西可能會佔用記憶體,例如:

  • WiredTiger 壓縮磁碟儲存,但記憶體中的數據未壓縮。
  • 預設情況下,WiredTiger 不會在每次送出時同步數據,因此日誌文件也在 RAM 中,這會佔用記憶體。還提到為了有效地使用 I/O,WiredTiger 將 I/O 請求(記憶體未命中)分塊在一起,這似乎也佔用了一些 RAM(事實上,臟頁(已更改/更新的頁面)有一個更新列表將它們儲存在 Concurrent SkipList中)。
  • WiredTiger 在其記憶體中保留多個版本的記錄(多版本並發控制,讀取操作在操作之前訪問最後送出的版本)。
  • WiredTiger 將數據的校驗和保存在記憶體中。
  • MongoDB 本身會消耗記憶體來處理打開的連接、聚合、伺服器端程式碼等

考慮到這些事實,依賴在show dbs;技術上並不正確,因為它只顯示了數據集的壓縮大小。

可以使用以下命令來獲取完整的數據集大小。

db.getSiblingDB('data_server').stats()
# OR
db.stats()

結果如下:

{
   "db" : "data_server",
   "collections" : 11,
   "objects" : 266565289,
   "avgObjSize" : 224.8413545621088,
   "dataSize" : 59934900658, # 60GBs
   "storageSize" : 22959984640,
   "numExtents" : 0,
   "indexes" : 41,
   "indexSize" : 7757348864, # 7.7GBs
   "ok" : 1
}

因此,實際數據集大小 + 其索引似乎佔用了大約 68GB 的​​記憶體。

考慮到所有這些,我猜現在記憶體使用量是可以預期的,很好的部分是限制 WiredTiger 記憶體大小是完全可以的,因為它非常有效地處理 I/O 操作(如上所述)。

還有OOM的問題,為了克服這個問題,由於我們沒有足夠的資源來取出mongodb,所以我們降低了oom_score_adj,以防止OOM暫時殺死重要程序(意思是我們告訴OOM不要殺死我們的所需的過程)。

引用自:https://dba.stackexchange.com/questions/148395