阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > 内存管理与缓存调优

内存管理与缓存调优

作者:陈川 阅读数:17658人阅读 分类: MongoDB

内存管理基础

MongoDB的内存管理直接影响查询性能和系统稳定性。WiredTiger存储引擎默认使用内存映射文件机制,将数据文件映射到内存地址空间。通过storage.wiredTiger.engineConfig.cacheSizeGB参数可配置缓存大小,建议设置为物理内存的50%-70%。当工作集超过缓存容量时会出现页面置换,可通过db.serverStatus().wiredTiger.cache监控缓存命中率:

// 查看缓存使用情况
const cacheStats = db.serverStatus().wiredTiger.cache;
print(`Bytes read into cache: ${cacheStats['bytes read into cache']}`);
print(`Bytes written from cache: ${cacheStats['bytes written from cache']}`);
print(`Pages evicted: ${cacheStats['pages evicted']}`);

工作集优化

工作集指活跃数据在内存中的驻留情况。通过db.collection.stats()可以分析集合的工作集特征:

const stats = db.orders.stats();
print(`Working set size: ${stats.size} bytes`);
print(`Index size: ${stats.totalIndexSize} bytes`);

优化策略包括:

  1. 垂直分片:将大字段分离到独立集合
  2. 热数据分离:将高频访问数据集中存放
  3. 预加载:启动时执行touch命令加载索引

索引内存优化

索引是内存消耗大户。复合索引设计应遵循ESR原则:

  • Equality(等值查询字段在前)
  • Sort(排序字段居中)
  • Range(范围查询字段在后)

示例优化前:

db.products.createIndex({ category: 1, price: 1, rating: -1 })

优化后:

db.products.createIndex({ category: 1, rating: -1, price: 1 })

使用hint()强制索引时需注意内存开销:

db.orders.find({ status: "shipped" })
  .sort({ created_at: -1 })
  .hint({ status: 1, created_at: -1 })

查询内存控制

通过cursor.maxTimeMS()allowDiskUse控制内存使用:

// 限制查询内存使用
db.reports.aggregate([
  { $match: { year: 2023 } },
  { $group: { _id: "$department", total: { $sum: "$sales" } } }
], {
  maxTimeMS: 30000,
  allowDiskUse: true
})

对于大结果集应使用批量获取:

const batchSize = 1000;
let cursor = db.logs.find().batchSize(batchSize);
while (cursor.hasNext()) {
  const docs = cursor.next();
  // 处理文档
}

写入内存优化

批量插入比单条插入内存效率高3-5倍:

// 低效方式
for (let i = 0; i < 1000; i++) {
  db.measurements.insert({ value: Math.random() });
}

// 高效方式
const bulk = db.measurements.initializeUnorderedBulkOp();
for (let i = 0; i < 1000; i++) {
  bulk.insert({ value: Math.random() });
}
bulk.execute();

更新操作使用$set而非全文档替换:

// 不推荐
db.users.update({ _id: 1 }, { name: "New", email: "new@example.com" });

// 推荐
db.users.update({ _id: 1 }, { $set: { name: "New", email: "new@example.com" } });

连接池调优

连接池大小影响内存占用和并发性能。计算公式:

最大连接数 = (核心数 * 2) + 有效磁盘数

配置示例:

# mongod.conf
net:
  maxIncomingConnections: 500
  serviceExecutor: "adaptive"

监控连接使用:

const connStats = db.serverStatus().connections;
print(`Available connections: ${connStats.available}`);
print(`Current in use: ${connStats.current}`);

操作系统级优化

Linux系统需要调整内核参数:

# 增加内存页大小
sysctl -w vm.nr_hugepages=1024

# 调整脏页比例
sysctl -w vm.dirty_ratio=20
sysctl -w vm.dirty_background_ratio=5

使用cgroups限制MongoDB内存:

cgcreate -g memory:mongodb
cgset -r memory.limit_in_bytes=16G mongodb

监控与诊断工具

实时监控工具:

// 当前内存状态
db.currentOp(true).inprog.forEach(op => {
  if(op.memUsage) print(`Op ${op.opid} using ${op.memUsage}MB`);
});

// 定期采样
setInterval(() => {
  const mem = db.serverStatus().mem;
  print(`Resident: ${mem.resident}MB Virtual: ${mem.virtual}MB`);
}, 5000);

使用mongotopmongostat分析热点:

mongotop --host localhost --rows 5 --seconds 3
mongostat --host localhost --discover --all

分片集群内存管理

分片集群需要特别关注:

  1. 配置服务器:保持小工作集
  2. 查询路由:增加mongos内存
  3. 数据分片:均衡分片分布

检查分片平衡状态:

db.adminCommand({ balancerStatus: 1 });
db.adminCommand({ getShardDistribution: "db.collection" });

调整chunk大小影响内存使用:

db.settings.update(
  { _id: "chunksize" },
  { $set: { value: 64 } },
  { upsert: true }
);

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

上一篇:慢查询分析与优化

下一篇:磁盘IO优化

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌