Skip to content

MongoDB 服务器状态指标

内存指标

系统内存使用

指标路径db.serverStatus().mem

关键指标

  • resident:MongoDB 进程实际使用的物理内存(MB)
  • virtual:MongoDB 进程使用的虚拟内存(MB)
  • mapped:映射到内存的数据文件大小(MB)
  • mappedWithJournal:包括日志文件在内的映射大小(MB)

解读与最佳实践

  • resident 通常不应超过系统可用内存的 80%
  • 如果 virtual 远大于 resident,可能存在内存泄漏
  • mapped 大小应与数据文件大小相符

示例

javascript
// 查看内存使用情况
const memStats = db.serverStatus().mem;
print(`物理内存使用: ${memStats.resident} MB`);
print(`虚拟内存使用: ${memStats.virtual} MB`);

WiredTiger 缓存状态

指标路径db.serverStatus().wiredTiger.cache

关键指标

  • bytes currently in the cache:当前缓存中的字节数
  • maximum bytes configured:缓存配置的最大字节数
  • bytes read into cache:从磁盘读取到缓存的字节数
  • bytes written from cache:从缓存写入到磁盘的字节数
  • pages evicted by application threads:应用线程驱逐的页面数
  • unmodified pages evicted:未修改页面驱逐数
  • modified pages evicted:修改页面驱逐数

解读与最佳实践

  • 缓存使用率(current/maximum)应保持在 80-90% 之间
  • 过高的驱逐率(evicted pages)可能表示缓存不足
  • 如果 modified pages evicted 持续增长,可能存在磁盘 I/O 瓶颈

示例

javascript
// 查看 WiredTiger 缓存状态
const cacheStats = db.serverStatus().wiredTiger.cache;
const usagePercent = (cacheStats["bytes currently in the cache"] / cacheStats["maximum bytes configured"]) * 100;
print(`WiredTiger 缓存使用率: ${usagePercent.toFixed(2)}%`);

连接指标

连接统计

指标路径db.serverStatus().connections

关键指标

  • current:当前活跃连接数
  • available:可用连接数
  • totalCreated:自实例启动以来创建的连接总数

解读与最佳实践

  • current 应远低于配置的最大连接数(默认 65536)
  • 持续增长的 totalCreated 可能表示连接泄漏
  • 设置合理的连接超时时间,避免空闲连接占用资源

示例

javascript
// 查看连接状态
const connStats = db.serverStatus().connections;
print(`当前连接数: ${connStats.current}`);
print(`可用连接数: ${connStats.available}`);
print(`总连接创建数: ${connStats.totalCreated}`);

操作统计指标

操作计数器

指标路径db.serverStatus().opcounters

关键指标

  • insert:插入操作总数
  • query:查询操作总数
  • update:更新操作总数
  • delete:删除操作总数
  • getmore:getMore 操作总数(用于游标)
  • command:命令操作总数

解读与最佳实践

  • 监控操作类型分布,了解业务特点
  • 突然的操作数增长可能表示异常流量
  • 结合时间窗口计算每秒操作数(OPS)

示例

javascript
// 查看操作统计
const opStats = db.serverStatus().opcounters;
print(`总插入操作: ${opStats.insert}`);
print(`总查询操作: ${opStats.query}`);
print(`总更新操作: ${opStats.update}`);
print(`总删除操作: ${opStats.delete}`);

操作计数器详情

指标路径db.serverStatus().opcountersRepl

关键指标

  • 副本集成员间复制操作的计数,包括 insert、query、update、delete 等

解读与最佳实践

  • 比较主节点和副本节点的操作计数器,检查复制延迟
  • 异常的复制操作计数可能表示复制问题

存储指标

存储引擎状态

指标路径db.serverStatus().storageEngine

关键指标

  • name:存储引擎名称(如 WiredTiger)
  • supportsCommittedReads:是否支持已提交读
  • readOnly:是否为只读模式

解读与最佳实践

  • 确认使用的存储引擎符合预期
  • 检查是否支持所需的功能

数据文件状态

指标路径db.serverStatus().metrics.document

关键指标

  • deleted:删除的文档数
  • inserted:插入的文档数
  • returned:查询返回的文档数
  • updated:更新的文档数

解读与最佳实践

  • 监控文档操作频率,了解数据变化趋势
  • 结合其他指标分析数据增长情况

锁定指标

全局锁定状态

指标路径db.serverStatus().globalLock

关键指标

  • totalTime:自实例启动以来的总锁定时间(微秒)
  • currentQueue:当前等待锁定的操作队列
    • read:读操作等待队列长度
    • write:写操作等待队列长度
  • activeClients:当前活跃客户端
    • read:活跃读客户端数
    • write:活跃写客户端数

解读与最佳实践

  • currentQueue.readcurrentQueue.write 持续增长表示锁竞争严重
  • 高锁等待时间可能导致性能下降
  • 优化慢查询和索引设计,减少锁持有时间

示例

javascript
// 查看全局锁定状态
const lockStats = db.serverStatus().globalLock;
print(`读操作等待队列: ${lockStats.currentQueue.read}`);
print(`写操作等待队列: ${lockStats.currentQueue.write}`);

数据库级锁定

指标路径db.serverStatus().locks

关键指标

  • 按数据库和集合分类的锁定统计
  • 包括锁定类型(R、W、r、w)和等待时间

解读与最佳实践

  • 识别锁定热点数据库和集合
  • 优化热点集合的查询和更新操作
  • 考虑分片分散负载

复制集指标

复制集状态

指标路径db.serverStatus().repl

关键指标

  • ismaster:是否为主节点
  • secondary:是否为副本节点
  • arbiters:仲裁节点列表
  • hosts:所有节点列表
  • primary:主节点地址
  • me:当前节点地址

解读与最佳实践

  • 确认当前节点角色符合预期
  • 检查复制集成员状态

复制延迟指标

指标路径db.serverStatus().repl

关键指标

  • optimeDate:当前操作时间戳
  • 结合 rs.status() 查看各节点的 lastHeartbeatlastHeartbeatRecv

解读与最佳实践

  • 监控复制延迟,确保数据及时同步
  • 复制延迟过大可能影响灾备能力

示例

javascript
// 查看复制集状态
const replStats = db.serverStatus().repl;
print(`是否为主节点: ${replStats.ismaster}`);
print(`是否为副本节点: ${replStats.secondary}`);
print(`主节点地址: ${replStats.primary}`);

网络指标

网络 I/O 统计

指标路径db.serverStatus().network

关键指标

  • bytesIn:接收的字节数
  • bytesOut:发送的字节数
  • numRequests:处理的请求数

解读与最佳实践

  • 监控网络流量,了解数据传输情况
  • 突然的流量变化可能表示异常
  • 结合操作计数分析网络效率

示例

javascript
// 查看网络统计
const netStats = db.serverStatus().network;
print(`总接收字节数: ${netStats.bytesIn}`);
print(`总发送字节数: ${netStats.bytesOut}`);
print(`总请求数: ${netStats.numRequests}`);

日志指标

日志记录统计

指标路径db.serverStatus().metrics.log

关键指标

  • global:全局日志统计
    • operations:日志操作数
    • latency:日志写入延迟

解读与最佳实践

  • 监控日志写入性能,避免日志成为瓶颈
  • 调整日志级别,平衡日志详细程度和性能

指标监控最佳实践

1. 建立基线

  • 在系统正常运行时收集指标,建立性能基线
  • 定期更新基线,适应业务变化
  • 对比当前指标与基线,识别异常

2. 设置合理的告警阈值

  • 内存使用率 > 85%
  • 连接数 > 70% 最大连接数
  • 锁等待队列长度持续 > 10
  • 复制延迟 > 30 秒
  • 磁盘使用率 > 80%

3. 综合分析指标

  • 单一指标异常可能不代表问题,需要综合分析
  • 例如:高 CPU 使用率 + 高锁等待 = 锁竞争问题
  • 高内存使用率 + 高驱逐率 = 缓存不足

4. 定期监控

  • 实时监控:使用 mongostat、mongotop 等工具
  • 历史监控:使用 MongoDB Atlas、Ops Manager 或 Prometheus + Grafana
  • 日志分析:定期分析慢查询日志和系统日志

5. 优化基于指标

  • 根据指标分析结果进行针对性优化
  • 优化索引、查询、配置参数或硬件资源
  • 优化后重新评估指标,验证优化效果

常见问题(FAQ)

Q1: 如何计算 MongoDB 每秒操作数(OPS)?

A1: 可以通过比较不同时间点的 opcounters 差值除以时间间隔来计算:

javascript
// 在时间 t1 记录操作计数
const t1 = new Date();
const opcounters1 = db.serverStatus().opcounters;

// 等待一段时间后再次记录
sleep(1000); // 等待 1 秒

const t2 = new Date();
const opcounters2 = db.serverStatus().opcounters;

// 计算每秒操作数
const timeDiff = (t2 - t1) / 1000;
const totalOps1 = opcounters1.insert + opcounters1.query + opcounters1.update + opcounters1.delete;
const totalOps2 = opcounters2.insert + opcounters2.query + opcounters2.update + opcounters2.delete;
const opsPerSecond = (totalOps2 - totalOps1) / timeDiff;

print(`每秒操作数: ${opsPerSecond.toFixed(2)}`);

Q2: WiredTiger 缓存使用率过高怎么办?

A2: 可以通过以下方式解决:

  • 增加系统内存
  • 调整 storage.wiredTiger.engineConfig.cacheSizeGB 参数
  • 优化查询,减少缓存使用
  • 考虑分片,分散缓存压力

Q3: 如何监控 MongoDB 磁盘 I/O?

A3: 可以使用以下方法:

  • iostat 命令(系统级)
  • db.serverStatus().wiredTiger.cache 中的读写统计
  • MongoDB Atlas 或 Ops Manager 中的磁盘 I/O 指标
  • 监控 db.serverStatus().network 中的字节传输

Q4: 连接数持续增长怎么办?

A4: 可能的原因和解决方案:

  • 应用程序连接泄漏:检查连接池配置,确保正确关闭连接
  • 短连接过多:使用连接池,增加连接复用
  • 配置问题:调整 maxIncomingConnections 参数
  • 考虑分片:分散连接到多个服务器

Q5: 如何区分正常和异常的指标值?

A5: 建立基线是关键。在系统正常运行时收集指标,了解正常范围。当指标超出基线 20-30% 时,需要进一步分析。同时,结合多个指标进行综合判断,单一指标异常可能不代表问题。