天天看點

Mongodb--記憶體管理MMAP

     MongoDB使用的是記憶體映射存儲引擎,即Memory Mapped Storage Engine,簡稱MMAP。

    MMAP可以把磁盤檔案的一部分或全部内容直接映射到記憶體,這樣檔案中的資訊位置就會在記憶體中有對應的位址空間,這時對檔案的讀寫可以直接用指針來做,而不需要read/write函數了,但這并不代表将檔案map到實體記憶體,隻有通路到這塊資料時才會被作業系統以Page的方式換到實體記憶體。MongoDB将記憶體管理工作交給作業系統的虛拟記憶體管理器來完成,這樣就大大簡化了MongoDB的工作,同時作業系統會将資料重新整理儲存到磁盤上。

  

  其實,從資料存儲原理來看,我更傾向于将mongodb歸類為硬碟資料庫,但是使用了mmap作為加速的手段而已。

       MongoDB應該配置設定的記憶體大小最好滿足記憶體大小>索引+熱資料+連接配接占用記憶體,通過db.stats()指令可檢視到目前資料庫的索引大小情況

     db.stats()

      下面是公司的MongoDB存儲了14億資料,占1.4T存儲空間

Mongodb--記憶體管理MMAP

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
}      
Mongodb--記憶體管理MMAP

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