MongoDB 监控(十一)serverStatus

梳理 MongoDB serverStatus 中连接、断言、锁、网络、操作计数、内存、metrics 和 WiredTiger 等关键字段,说明哪些适合转成监控指标和告警规则。

作者 快猫实习生

MongoDB 监控

这是 MongoDB 监控系列文章的第十一篇,前面几篇文章的链接如下:

各类数据库的监控方法都很类似,都是 agent 作为 client 连上去,执行一些命令获取各类指标。即:数据库本身提供了各类指标,但是不会直接暴露为 Prometheus metrics 等固定规范格式。通常每个库都是按照自己的格式输出,MongoDB 的话就是输出位 BSON 格式的数据。

之前系列的文章,我们已经介绍了诸如 db.stats()rs.status() 这样的命令,本文介绍 db.serverStatus(),serverStatus 提供了非常多的指标,我甚至怀疑 MongoDB 自己的某个研发人员都未必能搞明白所有指标。本文我们挑选一部分比较重要的指标做简要说明。

参考文章:https://developer.aliyun.com/article/405274

核心要点

  • db.serverStatus() 是 MongoDB 服务端状态信息的核心入口,覆盖连接、断言、锁、网络、操作计数、内存、metrics、WiredTiger 等多个类别。
  • 多数字段不是最终告警结论,而是排障证据;要结合业务流量、部署形态、MongoDB 版本和采集器转换方式一起理解。
  • 累加型字段通常需要转成每秒增量,Gauge 类型字段通常看当前值和趋势。
  • 优先关注连接风险、拒绝连接、断言异常、锁等待、网络突增、操作量变化、内存占用和 WiredTiger cache 相关指标。

Connection:连接数

mongos [direct: primary] admin> db.serverStatus().connections
{
  current: 56,
  available: 838804,
  totalCreated: 203,
  rejected: 0,
  active: 10,
  threaded: 56,
  exhaustIsMaster: Long('0'),
  exhaustHello: Long('7'),
  awaitingTopologyChanges: Long('7'),
  loadBalanced: Long('0')
}

作为一款 DB,连接数是肯定要监控的,当前连接数、可用连接数、总创建连接数、被拒绝连接数、活跃连接数等都是比较重要的指标。你可以配置一些告警规则,在可用连接数低于某个阈值时报警,另外也建议配置某个时间出现拒绝连接的时候告警。

连接数要和应用连接池一起看。current 高不一定代表故障,但 available 持续下降、rejected 出现增长、active 明显异常时,就需要排查连接池配置、连接泄露、客户端重试和数据库处理能力。

Asserts:断言事件

mongos [direct: primary] admin> db.serverStatus().asserts
{
  regular: 0,
  warning: 0,
  msg: 0,
  user: 1762,
  tripwire: 0,
  rollovers: 0
}

上例中 user 的 asserts 是 1762,表示用户操作引起的异常,比如你敲错了命令之类的。regular 和 warning 通常是 0,如果不为 0 需要关注,可以配置告警规则。

断言类指标适合作为“回到日志”的入口。它能提醒你发生过异常事件,但要确认具体原因,仍然需要结合 MongoDB 日志和当时执行的命令。

globalLock:全局锁队列

mongos [direct: primary] admin> db.serverStatus().globalLock
{
  totalTime: Long('82471123000'),
  currentQueue: { total: 0, readers: 0, writers: 0 },
  activeClients: { total: 0, readers: 0, writers: 0 }
}

globalLock 是 MongoDB 的全局锁,totalTime 是全局锁的总时间,currentQueue 是当前队列的情况,activeClients 是当前活跃的客户端情况。如果 currentQueue 较高表示有锁等待。

currentQueuetotalTime 更适合做实时观察,因为它能反映当前是否有读写操作在等待。排查时还要看业务操作类型、慢查询、索引和写入压力。

Locks:细粒度锁统计

mongos [direct: primary] admin> db.serverStatus().locks
{
  MultiDocumentTransactionsBarrier: { acquireCount: { W: Long('8') } },
  ReplicationStateTransition: {
    acquireCount: { w: Long('1877920'), W: Long('2') },
    acquireWaitCount: { w: Long('1') },
    timeAcquiringMicros: { w: Long('9683') }
  },
  Global: {
    acquireCount: { r: Long('2120459'), w: Long('900278'), W: Long('8') },
    acquireWaitCount: { r: Long('1') },
    timeAcquiringMicros: { r: Long('553') }
  },
  Database: {
    acquireCount: { r: Long('11282'), w: Long('809626'), R: Long('1'), W: Long('1') }
  },
  Collection: {
    acquireCount: { r: Long('56627'), w: Long('809612'), W: Long('9') }
  },
  Mutex: { acquireCount: { r: Long('19') } },
  oplog: { acquireCount: { r: Long('2834'), w: Long('2') } }
}

Locks 是颗粒度更小的锁,其中小写的 r、w 表示意向锁,类似乐观锁,即虽然使用了锁但事实上并没有锁住数据。大写的 R、W 是排它锁,它们的值也是累计值,通过它们每秒的增值,我们可以判断出我们系统的健康状况及业务访问的合理程度。

锁统计适合用于定位“为什么慢”。如果只看 QPS 和延迟,很难判断是流量增加、锁等待、磁盘压力还是查询低效。Locks 类指标可以补充锁竞争这一层证据。

Network:网络流量和请求数

mongos [direct: primary] admin> db.serverStatus().network
{
  bytesIn: Long('138851496'),
  bytesOut: Long('1311199561'),
  physicalBytesIn: Long('70953833'),
  physicalBytesOut: Long('1269348251'),
  numSlowDNSOperations: Long('0'),
  numSlowSSLOperations: Long('0'),
  numRequests: Long('322757'),
  tcpFastOpen: {
    kernelSetting: Long('1'),
    serverSupported: false,
    clientSupported: false,
    accepted: Long('0')
  },
  compression: {
    snappy: {
      compressor: { bytesIn: Long('169469387'), bytesOut: Long('120402691') },
      decompressor: { bytesIn: Long('118296614'), bytesOut: Long('206296460') }
    },
    zstd: {
      compressor: { bytesIn: Long('0'), bytesOut: Long('0') },
      decompressor: { bytesIn: Long('0'), bytesOut: Long('0') }
    },
    zlib: {
      compressor: { bytesIn: Long('0'), bytesOut: Long('0') },
      decompressor: { bytesIn: Long('0'), bytesOut: Long('0') }
    }
  },
  serviceExecutors: {
    passthrough: {
      threadsRunning: 56,
      clientsInTotal: 56,
      clientsRunning: 56,
      clientsWaitingForData: 0
    },
    inline: {
      threadsRunning: 0,
      clientsInTotal: 0,
      clientsRunning: 0,
      clientsWaitingForData: 0
    }
  },
  listenerProcessingTime: { durationMicros: Long('280117') }
}

某个时刻如果发现 MongoDB 访问慢,就可以来查看 network 相关的指标,是不是突发流量导致的。这里的值基本都是累加值,单调递增,需要使用 irate、rate 等函数来计算每秒的增量才比较有价值。

网络类指标适合和操作计数、返回数据量、客户端变化一起看。bytesOut 增长很快,可能只是查询返回数据变大;numRequests 增长很快,可能是业务流量或客户端重试导致。

Opcounters:操作计数器

mongos [direct: primary] admin> db.serverStatus().opcounters
{
  insert: Long('2'),
  query: Long('6445'),
  update: Long('1071'),
  delete: Long('70'),
  getmore: Long('50466'),
  command: Long('279910')
}

opcounters 是操作计数器,包括 insert、query、update、delete、getmore、command 等,这些值是累加值,可以通过计算每秒的增量来判断系统的健康状况。command 是除了 insert、query、update、delete、getmore 之外的操作,比如创建索引、删除索引、执行 db.runCommand() 等。

这些字段适合做 MongoDB QPS 或操作结构趋势图。操作量变化本身不等于异常,但它可以解释连接、延迟、网络和锁等待的变化。

Memory:进程内存

mongos [direct: primary] admin> db.serverStatus().mem
{
  bits: 64,
  resident: 151,
  virtual: 2941,
  supported: true,
  secureAllocByteCount: 288,
  secureAllocBytesInPages: 4096
}

Memory 是内存相关的指标,resident 是 MongoDB 进程占用的常驻内存,virtual 是 MongoDB 进程占用的虚拟内存。

内存指标要结合主机内存、WiredTiger cache 配置和系统 page fault 一起看。单个 residentvirtual 数值不足以判断是否异常。

Metrics:命令和文档操作明细

db.serverStatus().metrics

这个结果太多了,就不贴了。就是各种命令执行的数量统计,比如 metrics | command | failed 记录了命令失败的总次数,metrics | command | total 记录了命令执行的总次数。metrics | document | delete 等记录了对 Document 操作的次数。

metrics 适合补充比 opcounters 更细的维度,例如命令失败数、文档操作数等。做告警时,失败数增长通常比总数增长更值得关注。

wiredTiger:存储引擎指标

db.serverStatus().wiredTiger

这个结果也太多了,就不贴了。主要是关于 WiredTiger 存储引擎的指标,比如 wiredTiger | cache | bytes currently in the cache 记录了当前缓存的字节数,wiredTiger | cache | maximum bytes configured 记录了最大缓存的字节数。

WiredTiger 指标很多,不建议一开始全部放进仪表盘第一屏。可以先关注 cache 使用、dirty bytes、读写相关趋势,再根据具体问题下钻到更细字段。

serverStatus 指标使用建议

类别 适合回答的问题 告警或排障建议
connections 连接是否接近风险边界 关注可用连接下降、拒绝连接和活跃连接异常
asserts 是否有异常事件 尖刺或持续升高时回查 MongoDB 日志
globalLock / locks 是否存在锁等待或锁竞争 与延迟、慢查询和写入压力联动分析
network 是否有网络流量或请求突增 对累加值使用 rateirate
opcounters 操作量和操作结构是否变化 作为 QPS、读写比例和排障背景
mem MongoDB 进程内存占用情况 与主机内存、cache 和 page faults 一起看
metrics 命令失败和文档操作明细 失败类指标更适合告警
wiredTiger 存储引擎 cache 和读写状态 先抓关键 cache 指标,再按问题下钻

总结

serverStatus 是 MongoDB 监控最关键的命令之一,内容可以分成连接、断言、锁、网络、操作计数、内存、metrics 和 WiredTiger 等类别。本文只是先挑出一部分适合入门和排障的字段。真正落地告警时,不要把 serverStatus 的每个字段都变成规则,而要围绕可用性、性能、容量和复制状态设计少量高价值指标,再把其余字段作为下钻证据。

FAQ

Q1:serverStatus 和 dbStats 有什么区别? A:serverStatus 更偏服务端实时运行状态,dbStats 更偏数据库容量和空间统计。两者都重要,但适用的监控问题不同。

Q2:serverStatus 里的累加值应该怎么用? A:累加值通常要用 rateirate 转成单位时间增量,再用于趋势图或告警。直接看原始累计值容易误判。

Q3:是否需要把 serverStatus 所有字段都采集和展示? A:不建议。serverStatus 字段很多,第一阶段应先关注连接、断言、锁等待、网络、操作计数、内存和 WiredTiger cache 等关键类别,其余字段按排障需要下钻。

联系我们交流

延伸路径

继续看解决方案和产品对比

如果你正在做监控、可观测性或故障定位相关选型,建议从解决方案和产品对比继续往下看。

快猫星云 联系方式 快猫星云 联系方式
快猫星云 联系方式
快猫星云 联系方式
快猫星云 联系方式
快猫星云