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