mongodb 6、mongodb内存使用优化

1 问题
mongodb中某collection的记录数达到几千万级别的时候,mongodb占据的内存达到几十G,
节点内存耗尽,宕机
2 分析
2.1 问题定位
登陆mongodb,查看mongodb的服务状态
db.stats()
结果如下:
collections: 10
objects: 22591647
avgObjSize: 1204左右
dataSize: 27205964928
storageSize: 5663232000
indexes: 39
indexSize: 14344634368
ok: 1
2.2 mongodb索引 【mongodb 6、mongodb内存使用优化】
mongodb会将最近常用的值保存在RAM中,就有可能导致占用的内存变大。
官网描述如下:
Indexes that Hold Only Recent Values in RAM
Indexes do not have to fit entirely into RAM in all cases. If the value of the indexed field increments with every insert, and most queries select recently added documents; then MongoDB only needs to keep the parts of the index that hold the most recent or “right-most” values in RAM. This allows for efficient index use for read and write operations and minimize the amount of RAM required to support the index.
参考:
https://docs.mongodb.com/manual/tutorial/ensure-indexes-fit-ram/index.html
2.3 mongodb的缓存使用大小
3.4版本中,mongodb的wiredTiger内部缓存默认使用的大小为:
max(0.5 * (RAM - 1GB),256 MB)
修改mongodb的wiredTiger内部缓存大小:
将/etc/目录下的
mongod.conf备份为mongod.conf_bak
touch /etc/mongod.conf
填写如下内容:
# mongod.conf
# for documentation of all options, see:
#http://docs.mongodb.org/manual/reference/configuration-options/
# Where and how to store data.
storage:
wiredTiger:
engineConfig:
cacheSizeGB: 10
然后重启mongodb
centos环境下即执行:
systemctl restart mongod
或者执行如下命令:
mongod -f /etc/mongod.conf --auth &
参考:
https://docs.mongodb.com/v3.4/core/wiredtiger/
https://docs.mongodb.com/v3.4/reference/configuration-options/#storage-options
2.4 mongodb引擎分析
mongodb 3.4版本默认采用wiredTiger引擎,
mongodb有两部分内存,一个是WiredTiger internal cache,
一个是file system cache,wiredTigerCacheSizeGB参数设置的应该是 internal cache.
通过上面2.3中的cacheSizeGB只能限制内部缓存,而不能限制文件系统使用的缓存,mongodb
会使用剩余所有其他的文件系统缓存,所以会导致大规模部署内存耗尽的问题。
如果是在kubernetes环境,则需要借助resource limit来限制整体mongodb的内存使用。

2.5 mongodb缓存淘汰策略分析
如果 cacheSizeGB 配置为 10GB,可以认为 WiredTiger 引擎通过tcmalloc分配的内存总量不会超过10GB。为了控制内存的使用,WiredTiger 在内存使用接近一定阈值就会开始做淘汰,避免内存使用满了阻塞用户请求。
目前有4个可配置的参数来支持 wiredtiger 存储引擎的 eviction 策略(一般不需要修改),其含义是:
参数默认值含义
eviction_target80当 cache used 超过 eviction_target,后台evict线程开始淘汰 CLEAN PAGE
eviction_trigger95当 cache used 超过 eviction_trigger,用户线程也开始淘汰 CLEAN PAGE
eviction_dirty_target5当 cache dirty 超过 eviction_dirty_target,后台evict线程开始淘汰 DIRTY PAGE
eviction_dirty_trigger20当 cache dirty 超过 eviction_dirty_trigger, 用户线程也开始淘汰 DIRTY PAGE
在这个规则下,一个正常运行的 MongoDB 实例,cache used 一般会在 0.8 * cacheSizeGB 及以下,偶尔超出问题不大;如果出现 used>=95% 或者 dirty>=20%,并一直持续,说明内存淘汰压力很大,用户的请求线程会阻塞参与page淘汰,请求延时就会增加,这时可以考虑「扩大内存」或者 「换更快的磁盘提升IO能力」。
参考:
http://www.mongoing.com/archives/8781

3 解决方法
通过修改:
1) storage.wiredTiger.engineConfig.cacheSizeGB 的大小为10G(可根据实际情况调整),
2) 如果是k8s环境通过resource limit限制整体的mongodb缓存使用
所有参考:
[1] https://docs.mongodb.com/manual/tutorial/ensure-indexes-fit-ram/index.html
[2] https://docs.mongodb.com/v3.4/core/wiredtiger/
[3] https://docs.mongodb.com/v3.4/reference/configuration-options/#storage-options
[4] http://www.mongoing.com/archives/8781

    推荐阅读