• 博客访问: 883775
  • 博文数量: 495
  • 用 户 组: 普通用户
  • 注册时间: 2013-09-12 16:33
  • 认证徽章:
个人简介

疲劳了,才感觉一切都真切了。人生最重要的并不是努力,而是方向。压力不是有人比你努力,而是比你厉害几倍的人依然比你努力(反鸡汤:比你厉害的依然比你努力,那你努力有毛用)。

文章分类

全部博文(495)

文章存档

2018年(51)

2017年(89)

2016年(162)

2015年(192)

2013年(1)

我的朋友

分类: NoSQL

2018-05-15 17:58:18

起因

最近一直跑得好好的项目总是会莫名其妙的停了服务,最初的时候没有在意这个情况,觉得可能只是一个意外而已,可连着发生了好几次,就觉得有点怪异了,然后查看tomcat的log文件,就发现了问题所在了,内存不足

当时还觉得有点不理解,应该这台服务器的配置还是很高的,然后服务器上也只是跑了两个tomcat和一个mongo数据库,觉得不应该有这种问题的,然后就去查了一下资料,原来是mongo数据库在作祟,然后自己也用命令去查看了一下

真是不看不知道,一看吓一跳,一个mongo数据库占了服务器超过一半的内存,厉害的时候可以到70多,这时候才知道mongo吃内存的严重了。

MongoDB如何使用内存

        目前,MongoDB使用的是内存映射存储引擎,它会把磁盘IO操作转换成内存操作,如果是读操作,内存中的数据起到缓存的作用,如果是写操作,内存还可以把随机的写操作转换成顺序的写操作,总之可以大幅度提升性能。MongoDB并不干涉内存管理工作,而是把这些工作留给操作系统的虚拟缓存管理器去处理,这样的好处是简化了MongoDB的工作,但坏处是你没有方法很方便的控制MongoDB占多大内存,事实上MongoDB会占用所有能用的内存,所以最好不要把别的服务和MongoDB放一起。


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

大部分人都会和我一样,那就很好,如果不是的,可以自己修改过来:

不过要注意的是,ulimit的使用是有上下文的,最好放在MongoDB的启动脚本下。

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

当然,通过调整内核参数drop_caches也是可以释放缓存的:

平时可以通过mongo命令行来监控MongoDB的内存使用情况,如下所示:

还可以通过mongostat命令来监控MongoDB的内存使用情况,如下所示:

其中内存相关字段的含义是: 

mapped:映射到内存的数据大小  



mongodb占用内存非常高,这是因为官方为了提升存储的效率,设计就这么设计的。

但是大部分的个人开发者所购买的服务器内存并没有那么大,所以,我们需要配置下MongoDB的内存缓存大小,不然mongodb会占用非常多。

官方的配置缓存项处文档是这么解释的:

WiredTiger Options

--wiredTigerCacheSizeGB number

New in version 3.0.

Defines the maximum size of the internal cache that WiredTiger will use for all data.

With WiredTiger, MongoDB utilizes both the WiredTiger internal cache and the filesystem cache.

Changed in version 3.2: Starting in MongoDB 3.2, the WiredTiger internal cache, by default, will use the larger of either:

  • 60% of RAM minus 1 GB, or
  • 1 GB.

mongodb会尽可能的把所有的数据都缓存,以便提高效率。

以mongodb 3.2为例,WiredTiger内部缓存,默认会用掉

  • 60% * 内存 - 1GB
  • 1GB

当你的内存大于1GB,mongodb会用掉 内存的60% - 1GB 的内存作为缓存;

当你的内存小于1GB,mongodb会直接用掉1GB。

另外,MongoDB 3.4与3.2也是有区别的,MongoDB 3.4该配置项为:

storage.wiredTiger.engineConfig.cacheSizeGB

Type: float

The maximum size of the internal cache that WiredTiger will use for all data.

Changed in version 3.4: Values can range from 256MB to 10TB and can be a float. In addition, the default value has also changed.

Starting in 3.4, the WiredTiger internal cache, by default, will use the larger of either:

  • 50% of RAM minus 1 GB, or
  • 256 MB.

这样显然很不合理,对于大部分的个人开发,内存是宝贵的。所以,我们需要配置为MB。

配置项参考此处配置:WiredTiger cache size is only configurable in whole gigabytes.

下面是修改后的配置:/etc/mongod.conf

  1. # Where and how to store data.
  2. storage:
  3.   dbPath: /var/lib/mongo
  4.   #dbPath: /mongodata
  5.   journal:
  6.     enabled: true
  7. # engine:
  8.   mmapv1:
  9.     smallFiles: true
  10.   wiredTiger:
  11.     engineConfig:
  12.       configString : cache_size=512M

其实重点就是下面一项,配置之后,重启mongodb生效:

  1. wiredTiger:
  2.     engineConfig:
  3.       configString : cache_size=512M


发现一只32G内存的服务器,上边跑了几个 sharding 模式的 mongod,把内存吃到只剩下4G,8G swap 更是丁点不剩。

我见过吃内存的 mongod,可没见过大胃口的 mongod 啊。不过以前我也没怎么见到在这么大内存的机器上跑的 mongod。不过不管如何,把 swap 全吃掉总归是不对的。

于是翻了翻 mongodb 源码,发现出现这种情况还真是机器的配置的问题。代码里有这么一段(在 GitHub 上的位置):

  1. if (cacheSizeGB == 0) {
  2.     // Since the user didn't provide a cache size, choose a reasonable default value.
  3.     // We want to reserve 1GB for the system and binaries, but it's not bad to
  4.     // leave a fair amount left over for pagecache since that

大概这就是决定它自己要用多少内存的代码了。先留出1G,然后再留出40%,剩下的能吃就吃!于是,好几只 mongod 开始抢食了!默认vm.swappiness=60的内核看到内存快用完了,于是开始往 swap 挪。结果造成内核挪多少,mongod 吃多少……

这种情况在机器内存少的时候没有出现,大概是因为内存少的时候,mongod 留出的比例比较高,内核就没那么卖力地把数据往 swap 上挪了。而且这次是好几只 mongod 哄抢呢。


参考:
http://www.cnblogs.com/bonelee/p/8366050.html
https://blog.csdn.net/zhongbeida_xue/article/details/52857901

阅读(878) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~
评论热议
请登录后评论。

登录 注册