mongodb

来源:互联网 发布:matlab最优算法 编辑:程序博客网 时间:2024/06/06 17:24

点击打开链接



overview

     MongoDB使用的是内存映射存储引擎,即Memory Mapped Storage Engine,简称MMAP。MMAP可以把磁盘文件的一部分或全部内容直接映射到内存,这样文件中的信息位置就会在内存中有对应的地址空间,这时对文件的读写可以直接用指针来做,而不需要read/write函数了,但这并不代表将文件map到物理内存,只有访问到这块数据时才会被操作系统以Page的方式换到物理内存。MongoDB将内存管理工作交给操作系统的虚拟内存管理器来完成,这样就大大简化了MongoDB的工作,同时操作系统会将数据刷新保存到磁盘上,下图就是MMAP的简要工作原理图







内存使用情况

查看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

Mongodb内存大小配置建议

MongoDB应该分配的内存大小最好满足内存大小>索引+热数据+连接占用内存,通过db.stats()命令可查看到当前数据库的索引大小情况
bj1-farm1:PRIMARY> db.stats()
{
"db" : "yc_driver",                  //当前数据库
"collections" : 5,                   //当前数据库多少表
"objects" : 2911281,                //当前数据库所有表多少条数据 
"avgObjSize" : 240.28991086741541,  //每条数据的平均大小
"dataSize" : 699551452,            //所有数据的总大小
"storageSize" : 858513408,          //所有数据占的磁盘大小
"numExtents" : 21,                 
"indexes" : 5,                     //索引数
"indexSize" : 569229472,          //索引大小
"fileSize" : 2080374784,         //预分配给数据库的文件大小
"nsSizeMB" : 16,
"dataFileVersion" : {
"major" : 4,
"minor" : 5
},
"extentFreeList" : {
"num" : 0,
"totalSize" : 0
},
"ok" : 1
}

参考文献

http://blog.chinaunix.net/uid-25979788-id-3255769.html
http://www.cnblogs.com/Creator/archive/2012/11/04/2754110.html


点击打开链接

目前,MongoDB使用的是内存映射存储引擎,它会把数据文件映射到内存中,如果是读操作,内存中的数据起到缓存的作用,如果是写操 

作,内存还可以把随机的写操作转换成顺序的写操作,总之可以大幅度提升性能。MongoDB并不干涉内存管理工作,而是把这些工作留给操 

作系统的虚拟内存管理器去处理,这样做的好处是简化了MongoDB的工作,但坏处是你没有方法很方便的控制MongoDB占多大内存,幸运 

的是虚拟内存管理器的存在让我们多数时候并不需要关心这个问题。 

MongoDB的内存使用机制让它在缓存重建方面更有优势,简而言之:如果重启进程,那么缓存依然有效,如果重启系统,那么可以通过拷贝 

数据文件到/dev/null的方式来重建缓存,更详细的描述请参考:Cache Reheating – Not to be Ignored。 

有时候,即便MongoDB使用的是64位操作系统,也可能会遭遇OOM问题,出现这种情况,多半是因为限制了内存的大小所致,可以这样查 

看当前值: 

shell> ulimit -a | grep memory 
多数操作系统缺省都是把它设置成unlimited的,如果你的操作系统不是,可以这样修改: 

shell> ulimit -m unlimitedshell> ulimit -v unlimited 
注:ulimit的使用是有上下文的,最好放在MongoDB的启动脚本里。 

有时候,MongoDB连接数过多的话,会拖累性能,可以通过serverStatus查询连接数: 

mongo> db.serverStatus().connections 
每个连接都是一个线程,需要一个Stack,Linux下缺省的Stack设置一般比较大: 

shell> ulimit -a | grep stackstack size              (kbytes, -s) 10240 
至于MongoDB实际使用的Stack大小,可以用如下命令确认(单位:K): 

shell> cat /proc/$(pidof mongod)/limits | grep stack | awk -F 'size' '{print int($NF)/1024}' 
如果Stack过大(比如:10240K)的话没有意义,简单对照命令结果中的Size和Rss: 

shell> cat /proc/$(pidof mongod)/smaps | grep 10240 -A 10 
所有连接消耗的内存加起来会相当惊人,推荐把Stack设置小一点,比如说1024: 

shell> ulimit -s 1024 
注:从开始,MongoDB会在启动时自动设置Stack。 

有时候,出于某些原因,你可能想释放掉MongoDB占用的内存,不过前面说了,内存管理工作是由虚拟内存管理器控制的,幸好可以使用 

MongoDB内置的closeAllDatabases命令达到目的: 

mongo> use adminmongo> db.runCommand({closeAllDatabases:1}) 
另外,通过调整内核参数drop_caches也可以释放缓存: 

shell> sysctl -w vm.drop_caches=1 
平时可以通过mongo命令行来监控MongoDB的内存使用情况,如下所示: 

mongo> db.serverStatus().mem:{    "resident" : 22346,    "virtual" : 1938524,    "mapped" : 962283} 
还可以通过mongostat命令来监控MongoDB的内存使用情况,如下所示: 

shell> mongostatmapped  vsize    res faults  940g  1893g  21.9g      0 
其中内存相关字段的含义是: 

mapped:映射到内存的数据大小 
visze:占用的虚拟内存大小 
res:占用的物理内存大小 
注:如果操作不能在内存中完成,结果faults列的数值不会是0,视大小可能有性能问题。 

在上面的结果中,vsize是mapped的两倍,而mapped等于数据文件的大小,所以说vsize是数据文件的两倍,之所以会这样,是因为本例中,MongoDB开启了journal,需要在内存里多映射一次数据文件,如果关闭journal,则vsize和mapped大致相当。 

如果想验证这一点,可以在开启或关闭journal后,通过pmap命令来观察文件映射情况: 

shell> pmap $(pidof mongod) 
到底MongoDB配备多大内存合适?宽泛点来说,多多益善,如果要确切点来说,这实际取决于你的数据及索引的大小,内存如果能够装下全 

部数据加索引是最佳情况,不过很多时候,数据都会比内存大,比如本文所涉及的MongoDB实例: 

mongo> db.stats(){    "dataSize" : 1004862191980,    "indexSize" : 1335929664} 
本例中索引只有1G多,内存完全能装下,而数据文件则达到了1T,估计很难找到这么大内存,此时保证内存能装下热数据即可,至于热数 

据是多少,取决于具体的应用。如此一来内存大小就明确了:内存 > 索引 + 热数据,最好有点富余,毕竟操作系统本身正常运转也需要消耗一部分内存。 


0 0