rs.status()必须在主节点执行,其members数组中health、state、optime.durableOpTime.ts三字段是诊断核心:health=1表心跳正常,state数值码表真实角色,durableOpTime.ts差值反映精确oplog延迟。

直接在连接到副本集主节点的 mongosh 会话中执行 rs.status(),就能拿到最权威、实时的复制状态快照——它不是“大概看看”,而是 MongoDB 内部状态的原始投射,所有健康判断都应以此为依据。
rs.status() 必须在主节点上运行
如果连的是 secondary 节点,默认情况下 rs.status() 会报错:not master and slaveOk=false。这不是权限问题,而是设计使然:副本集元数据(如选举任期、投票权重、同步源关系)只由主节点权威维护。
- 先确认角色:
rs.isMaster().ismaster返回true才算主节点 - 若当前连的是 secondary,加
rs.secondaryOk()可临时允许读取(但rs.status()仍不支持),必须重连到 primary - 在 mongos 或 config server 上执行会报
command rs.status not found,因为该命令仅对 replica set 成员有效
从 members 数组里盯住三个关键字段
rs.status().members 是诊断核心,每个成员对象里真正要盯的只有三项:
-
health:值为1表示心跳正常;0表示已失联超heartbeatTimeoutMillis(默认 10 秒),但注意:短暂网络抖动可能还没触发 failover,得结合lastHeartbeat看时间戳 -
state:数值型状态码,1= PRIMARY,2= SECONDARY,7= ARBITER,8= DOWN;别只信字符串字段stateStr,它可能缓存旧值(比如刚故障的节点还显示 "SECONDARY") -
optime.durableOpTime.ts:这个 Timestamp 才是真实同步位点;用它和主节点的rs.status().optimes.durableOpTime.ts做差值,才能算出精确延迟(单位是 oplog 序号,不是秒)
复制延迟不能只看 rs.printSecondaryReplicationInfo()
rs.printSecondaryReplicationInfo() 输出的 “X secs behind” 是个粗略估算,它把 optime 和本地系统时间做减法,一旦节点时钟不同步(哪怕差几百毫秒),结果就不可信。
- 真要看延迟,对比主节点和 secondary 的
durableOpTime.ts:比如主节点是Timestamp(1747052340, 3),secondary 是Timestamp(1747052330, 1),说明落后 10 条 oplog 记录 - oplog 增长速度取决于写入压力;10 条可能对应 200ms,也可能对应 5 秒——得结合
db.getSiblingDB("local").oplog.rs.stats().avgObjSize和写入 QPS 估算 - 如果 secondary 的
optime长期不更新,先检查syncSourceHost是否为空,再查lastHeartbeatRecv时间是否停滞
myState 和 term 字段暴露选举稳定性
myState 是当前节点角色快照,term 是选举任期号;二者配合能看出集群是否频繁震荡:
- 如果
term在几分钟内连续增长(比如从 5 → 6 → 7),说明发生了多次非预期选举,大概率是网络分区或磁盘 I/O 卡顿导致 heartbeat 失败 -
myState: 3(RECOVERING)或myState: 5(STARTUP2)属于中间态,持续超过 30 秒就要查日志:grep "replSet" /var/log/mongodb/mongod.log - 仲裁节点(
arbiterOnly: true)的myState永远是7,它的health为1只代表心跳通,不参与数据同步——别把它当成可用的 secondary
真正难啃的点不在命令怎么输,而在于把 optime.ts、term、lastHeartbeatRecv 这几个字段的时间语义串起来:它们各自基于不同逻辑时钟,混用就会误判。健康 ≠ 绿色,延迟 ≠ 秒数,状态码 ≠ 角色名——所有字段都得放在副本集协议上下文中读。

















