MongoDB使用的是記憶體映射存儲引擎,即Memory Mapped Storage Engine,簡稱MMAP。
MMAP可以把磁盤檔案的一部分或全部内容直接映射到記憶體,這樣檔案中的資訊位置就會在記憶體中有對應的位址空間,這時對檔案的讀寫可以直接用指針來做,而不需要read/write函數了,但這并不代表将檔案map到實體記憶體,隻有通路到這塊資料時才會被作業系統以Page的方式換到實體記憶體。MongoDB将記憶體管理工作交給作業系統的虛拟記憶體管理器來完成,這樣就大大簡化了MongoDB的工作,同時作業系統會将資料重新整理儲存到磁盤上。
其實,從資料存儲原理來看,我更傾向于将mongodb歸類為硬碟資料庫,但是使用了mmap作為加速的手段而已。
MongoDB應該配置設定的記憶體大小最好滿足記憶體大小>索引+熱資料+連接配接占用記憶體,通過db.stats()指令可檢視到目前資料庫的索引大小情況
db.stats()
下面是公司的MongoDB存儲了14億資料,占1.4T存儲空間

shard1:SECONDARY> db.stats()
{
"db" : "database", // 目前使用的資料庫
"collections" : 662, // 多少張表
"objects" : 1405948982, // 所有表的多少條資料 -- 14.05億
"avgObjSize" : 1134.649427176014, // 平均每條資料大小
"dataSize" : 1595259207065, // 總資料大小 -- 1.485TB
"storageSize" : 768647647232, // 所有資料占磁盤的大小 -- 715.85G
"numExtents" : 0,
"indexes" : 1098, // 索引數量
"indexSize" : 173431967744, // 索引大小 -- 160G
"ok" : 1
}

2、 修改MongoDB使用的記憶體大小
從3.4版本開始,預設情況下,WieldGigd内部緩存将使用下面2種中更大的一種:50% of (RAM - 1 GB) 和256 MB。通過檔案系統緩存,MongoDB的自動使用未被wiredtiger緩存或由其他程序使用所有可用記憶體。調整WiredTiger内部緩存的方法: storage.wiredTiger.engineConfig.cacheSizeGB 和 --wiredTigerCacheSizeGB
看來不設定的話,預設會使用50% of (RAM - 1 GB)的記憶體。于是在配置檔案設定了storage.wiredTiger.engineConfig.cacheSizeGB為0.5,也就是500M,再看測試結果:
vim /etc/mongod.conf
storage:
dbPath: /var/lib/mongodb
journal:
enabled: true
# engine:
# mmapv1:
wiredTiger:
engineConfig:
cacheSizeGB: 0.5
可以看到,MongoDB所占的實體記憶體穩定在了630M左右,說明設定确實生效了。
3、記憶體使用情況
檢視Linux虛拟記憶體管理器是否對記憶體做了限制,如果顯示為unlimited表示無限制
[jiangjianjian@f1-mongo1 ~]$ ulimit -a | grep memory
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
virtual memory (kbytes, -v) unlimited
修改虛拟記憶體限制
[jiangjianjian@f1-mongo1 ~]$ ulimit -m unlimited
[jiangjianjian@f1-mongo1 ~]$ ulimit -v unlimited
檢視目前MongoDB的連接配接數
mongo中每一個連接配接都是一個線程,需要一個stack,從結果中可看到目前連接配接數為2372,最大連接配接數為51200
bj1-farm1:PRIMARY> db.serverStatus().connections
{
"current" : 2372,
"available" : 48828,
"totalCreated" : NumberLong(185449264)
}
Linux下預設的Stack大小檢視
[jiangjianjian@f1-mongo1 ~]$ ulimit -a | grep stack
stack size (kbytes, -s) 10240
MongoDB實際使用的Stack大小檢視
可以用如下指令确認(機關:K)
[root@f1-mongo1 journal]# cat /proc/$(pidof mongod)/limits | grep stack | awk -F 'size' '{print int($NF)/1024}'
10240
調整stack大小的方法
如果Stack過大,比如上述的10240K,我們可以通過以下指令調整stack大小
[root@f1-mongo1 journal]# ulimit -s 1024
MongoDB釋放記憶體的指令
mongo> use admin
mongo> db.runCommand({closeAllDatabases:1})
Mongodb自帶指令檢視其記憶體使用情況
其中resident代表實體記憶體使用情況,機關為M;而virtual為虛拟記憶體使用情況,mapped是映射到記憶體的資料大小。這裡虛拟記憶體是mapped的兩倍,是因為我們開啟了Journal日志,需要在記憶體中多映射一次,大概就是它的兩倍了。如果關閉Journal日志,虛拟記憶體大小将和mapped大小相當。
bj1-farm1:PRIMARY> db.serverStatus().mem
"bits" : 64,
"resident" : 46662,
"virtual" : 326198,
"supported" : true,
"mapped" : 161399,
"mappedWithJournal" : 322798
top指令檢視
這裡還可以通過top指令觀察mongodb的記憶體使用情況,如下圖,可看到其中的VIRT和RES與上述指令的結果一樣
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
12603 mongod 20 0 318g 45g 44g S 28.0 72.1 27230:21 mongod
free指令檢視
而再通過free指令可檢視到記憶體占用中有多少是因為資料緩存和cache,關于如何檢視free指令,參見http://blog.csdn.net/cug_jiang126com/article/details/42266653
[jiangjianjian@f1-mongo1 ~]$ free
total used free shared buffers cached
Mem: 65921032 65262376 658656 0 274264 61742808
-/+ buffers/cache: 3245304 62675728
Swap: 100663288 11884 100651404