优化MongoDB内存使用,可以通过一下几点来降低系统内存占用,本次主要配置WiredTiger Cache来实现
-
WiredTiger Cache:
- MongoDB 使用 WiredTiger 存储引擎,其缓存使用最近最少使用 (LRU) 算法管理。频繁访问的数据会保留在内存中,而不常访问的数据会被剔除。
- 可以通过
storage.wiredTiger.engineConfig.cacheSizeGB
配置缓存大小,从而间接控制内存使用。
-
Page Eviction:
- WiredTiger 存储引擎会定期执行页面驱逐 (page eviction) 操作,将不常使用的页面从内存中移除。这样可以保持内存的合理使用。
-
TTL Indexes:
- MongoDB 提供 TTL (Time-To-Live) 索引,允许自动删除超过指定时间的数据。虽然这主要用于管理存储空间,但也有助于减少内存占用。
-
Inactive Data Handling:
- 在分片集群 (sharded cluster) 中,不活跃的数据可以通过迁移分片来减少某些节点上的内存压力。将不常访问的数据分配到较少使用的节点上,减少高负载节点的内存占用。
-
Journaling and Snapshotting:
- MongoDB 的持久化机制会定期进行日志记录和快照,这些操作会影响内存使用。适当配置日志记录和快照策略可以帮助管理内存。
设置WiredTiger
存储引擎和缓存大小
修改配置文件后需要重启MongoDB
storage:
wiredTiger:
engineConfig:
cacheSizeGB: 16
重启MongoDB
sudo systemctl restart mongod
运行时动态调整缓存大小
db.adminCommand({ setParameter: 1, "wiredTigerEngineRuntimeConfig": "cache_size=2GB" });
查看当前的存储引擎
db.serverStatus().storageEngine
查询当前设置的缓存大小【直接查看配置文件也可以】
db.serverStatus().wiredTiger.cache["maximum bytes configured"]
查看监控和分析
登录MongoDB
mongo "mongodb://admin:password@localhost:27017/admin"
创建具有监控权限的用户
db.getSiblingDB("admin").createUser({
user: "statuser",
pwd: "statpassword",
roles: [
{ role: "clusterMonitor", db: "admin" }
]
})
监控 MongoDB 实例的状态
mongostat --uri "mongodb://statuser:statpassword@localhost:27017/?authSource=admin" --discover
mongostat
的输出字段
host insert query update delete getmore command dirty used flushes vsize res qrw arw net_in net_out conn time
localhost:27017 10 *0 *0 *0 0 1|0 0.0% 70.3% 0 33.7G 32.1G 0|0 1|0 6.99k 44.8k 24 May 29 11:08:00.238
localhost:27017 7 *0 *0 *0 0 0|0 0.0% 70.3% 0 33.7G 32.1G 0|0 1|0 5.57k 44.2k 24 May 29 11:08:01.245
localhost:27017 4 *0 *0 *0 0 2|0 0.0% 70.3% 0 33.7G 32.1G 0|0 1|0 3.03k 44.8k 24 May 29 11:08:02.241
字段解释
- host: MongoDB 实例的地址和端口。
- insert: 每秒插入的文档数(10, 7, 4)。
- query: 每秒查询的次数(未发生)。
- update: 每秒更新的次数(未发生)。
- delete: 每秒删除的次数(未发生)。
-
getmore: 每秒
getmore
操作的次数(未发生)。 -
command: 每秒执行的命令次数。分为读命令和写命令,如
1|0
和2|0
。 - dirty: 存储引擎的脏数据百分比(0.0%)。
- used: 存储引擎的缓存使用百分比(70.3%)。
-
flushes: 每秒执行的
fsync
操作次数(未发生)。 - vsize: 虚拟内存大小(33.7GB)。
- res: 常驻内存大小(32.1GB)。
- qrw: 排队的读写操作数量(查询 | 写入,均为 0)。
- arw: 活动的读写操作数量(查询 | 写入,均为 1|0)。
- net_in: 每秒网络输入量(6.99kB, 5.57kB, 3.03kB)。
- net_out: 每秒网络输出量(44.8kB, 44.2kB)。
- conn: 当前连接数(24)。
- time: 当前时间。
used:存储引擎的缓存使用百分比解释
在 MongoDB 的 mongostat
输出中,used
字段表示存储引擎(通常是 WiredTiger)缓存使用的百分比。这个百分比是存储引擎实际使用的缓存内存量与分配给存储引擎的总缓存内存量之间的比值。具体来说:
- Numerator(分子):存储引擎实际使用的缓存内存量。
- Denominator(分母):分配给存储引擎的总缓存内存量。
详细解释
MongoDB 的 WiredTiger 存储引擎使用一个内部缓存来管理内存中的数据。缓存大小可以通过 cacheSizeGB
参数配置。如果没有特别配置,WiredTiger 默认将服务器总内存的 50% 分配给缓存。
比值计算公式
used% = 实际使用的缓存内存/分配的总缓存内存 * 100%
示例
假设你在 mongod.conf
中配置了 WiredTiger 的缓存大小为 16 GB:
storage:
wiredTiger:
engineConfig:
cacheSizeGB: 16
然后在 mongostat
输出中看到 used
字段为 70.3%:
host insert query update delete getmore command dirty used flushes vsize res qrw arw net_in net_out conn time
localhost:27017 10 *0 *0 *0 0 1|0 0.0% 70.3% 0 33.7G 32.1G 0|0 1|0 6.99k 44.8k 24 May 29 11:08:00.238
这表示 WiredTiger 实际使用了约 11.248 GB 的缓存内存(即 70.3% × 16 GB)。
优化 MongoDB 实例的内存使用,特别是降低常驻内存(res
)的占用
1. 调整工作集
确保工作集(即正在频繁访问的数据集)能够适应可用的内存。如果工作集过大,超出了物理内存容量,MongoDB 会频繁进行磁盘 I/O 操作,从而影响性能。
2. 索引优化
索引是提高查询性能的关键,但过多的索引会消耗大量内存。请按照以下步骤优化索引:
- 分析查询模式:确定哪些查询最常执行,然后为这些查询建立适当的索引。
- 移除不必要的索引:定期审查和删除不再使用或效率不高的索引。
- 复合索引:对于多字段查询,使用复合索引来提高查询效率。
// 创建复合索引示例
db.collection.createIndex({ field1: 1, field2: 1 });
3. 合并小文档
如果文档太小且数量很多,会增加内存消耗和索引开销。考虑将小文档合并成大文档,减少文档数量,从而降低内存使用。
4. 启用压缩
MongoDB 提供了多种存储引擎和压缩选项,例如 WiredTiger 提供了 zlib 和 snappy 压缩。
- 启用数据压缩:通过配置文件或启动参数启用压缩,减少数据和索引的内存占用。
# mongod.conf 示例
storage:
wiredTiger:
engineConfig:
cacheSizeGB: 16
collectionConfig:
blockCompressor: snappy
5. 调整 WiredTiger 缓存
WiredTiger 是 MongoDB 的默认存储引擎,可以通过调整其缓存大小来优化内存使用。
- 缓存大小配置:适当调整 WiredTiger 的缓存大小,确保留有足够的内存供操作系统和其他进程使用。
# mongod.conf 示例
storage:
wiredTiger:
engineConfig:
cacheSizeGB: 16
6. 配置系统参数
- 内存分配:确保 MongoDB 进程有足够的物理内存可用,并且操作系统的虚拟内存设置合理。
- 透明大页:禁用透明大页(Transparent Huge Pages, THP),减少内存碎片。
# 禁用透明大页
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag
7. 清理未使用的数据
定期清理未使用的数据和集合,减少数据库的总体大小和内存占用。
8. 监控和调整
- 监控工具:使用监控工具(如 MongoDB Ops Manager、Grafana 等)实时监控内存使用情况。
- 性能分析:定期进行性能分析和内存使用审计,找出内存使用的热点并进行优化。