关于Mongodb的内存使用

参考:https://enterprisezine.jp/dbonline/detail/7098

mongodb有两种存储引擎
■ mmap
在版本3.2之前,该方式一直都是mongodb的默认存储引擎

■ wired tiger
出生在版本2.8,版本3.2以后成了mongodb的默认存储引擎

关于mmap.
mongodb没有对内存的使用进行管理,它将这些任务都交给OS,其实就是利用的linux系统的mmap.

什么是mmap?
mmap就是文件系统上,将文件映射到内存中,进程可以快速的读取存在于内存上的文件的内容。
进程刚启动时,文件是不会映射到内存中。进程初次读取文件是从内存中,读完之后才会将文件放置于内存中。
那之后文件就留在内存上,第二回及之后的访问就有内存应答。
那之后当内存满了的时候会有溢出的现象,mmap的算法将会使一部分文件从内存中退出。这也就是所谓的页故障。

mongodb和mmap
在mongodb里,是将数据目录下的数据文件加载到内存中。
数据目录中存在着,数据库名.0,数据库名.1...这样的文件。
如下:
[db]# ls -lh
合計 545M
drwxr-xr-x 2 root root 4.0K 11月 27 22:40 2014 journal
-rw------- 1 root root  64M 11月 27 22:40 2014 local.0
-rw------- 1 root root  16M 11月 27 22:40 2014 local.ns
-rwxr-xr-x 1 root root    6 11月 27 22:40 2014 mongod.lock
-rw------- 1 root root  64M 11月 27 21:15 2014 test.0 ★
-rw------- 1 root root 128M 11月 27 21:15 2014 test.1 ★
-rw------- 1 root root 256M 11月 27 21:15 2014 test.2 ★
-rw------- 1 root root  16M 11月 27 21:15 2014 test.ns

数据文件中的内容


数据文件中的内容就是数据本身(BSON)和索引。
数据文件中的数据用的extent和索引用的extend以可变长度保存着。
http://blog.mongolab.com/2014/01/how-big-is-your-mongodb/

mongodb加载到内存的时间

刚启动时数据和Index都不会加载到内存
那是因为使用的是mmap

举个例子,看一下hoge Collection

> db.hoge.stats()
{
        "ns" : "test.hoge",
        "count" : 1740681,
        "size" : 83552848,
        "avgObjSize" : 48,
        "storageSize" : 123936768,
        "numExtents" : 11,
        "nindexes" : 4,
        "lastExtentSize" : 37625856,
        "paddingFactor" : 1,
        "systemFlags" : 0,
        "userFlags" : 1,
        "totalIndexSize" : 228331152,
        "indexSizes" : {
                "_id_" : 50846544,
                "a_1" : 43807008,
                "_id_1_a_1" : 66838800,
                "a_1__id_1" : 66838800
        },
        "ok" : 1
}

数据大小83552848约80M,索引大小是228331152约220M,看一下serverStatus().
db.serverStatus().mem
{
        "bits" : 64,
        "resident" : 47,
        "virtual" : 1482,
        "supported" : true,
        "mapped" : 544, 
        "mappedWithJournal" : 1088
}

现在实际占用了47M的内存,也就是说hoge collection的数据和索引还没有全被加载到内存中。

随着查询的别执行,渐渐的都会被加载到内存。
刚启动的时候内存中啥也没有,随着检索的进行,必要的数据和索引就会渐渐的被加载到内存。

因此,Mongodb刚启动的时候应答的速度会有些慢。

预加热


预加热的话,就可以将常用的数据加入到内存中。
语法如下

db.runCommand({ touch: "collectionName", data: [true|false], index: [true|false] })


>  db.serverStatus().mem
{
        "bits" : 64,
        "resident" : 48, ←启动后48M
        "virtual" : 1482,
        "supported" : true,
        "mapped" : 544,
        "mappedWithJournal" : 1088
}
举个例子,刚才的例子,只将索引加载到内存中
db.runCommand({ touch: "hoge", data: false, index: true })
{
        "indexes" : {
                "num" : 4,
                "numRanges" : 30,
                "millis" : 48
        },
        "ok" : 1
}

> db.serverStatus().mem
{
        "bits" : 64,
        "resident" : 324,←只将索引加载到内存
        "virtual" : 1482,
        "supported" : true,
        "mapped" : 544,
        "mappedWithJournal" : 1088
}

清空内存

查看mongodb的内存使用率
top -p (pidof mongod)
或者
top
shift+m

有时候,出于某些原因,你可能想释放掉MongoDB占用的内存,不过前面说了,内存管理工作是由虚拟内存管理器控制的,所以通常你只能通过重启服务来释放内存,你一定不齿于这样的方法,幸好可以使用MongoDB内置的closeAllDatabases命令达到目的:

use admin <--必须切换到admin collection
db.runCommand({closeAllDatabases:1})

另外,通过调整内核参数drop_caches也可以释放缓存:
sysctl -w vm.drop_caches=1


平时可以通过mongo命令行来监控MongoDB的内存使用情况,如下所示:
db.serverStatus().mem:
mongostat


使用top命令记录mongodb进程的内存使用状况

n 设置退出前屏幕刷新的次数
d 指定每两次屏幕信息刷新之间的时间间隔。
b 将top输出编排成适合输出到文件的格式,可以使用这个选项创建进程日志
p 通过指定监控进程ID来仅仅监控某个进程的状态

top -d 300 -b -n 2016 -p 2793 > plog &
以间隔为5分钟一次,将进程2793(mongodb)的状况刷新2016次(一周),导入到plog文件里。

猜你喜欢

转载自baiyunliu.iteye.com/blog/2327075
今日推荐