delay单位是秒,表示secondary当前应用的oplog时间戳与primary最新oplog时间戳的逻辑延迟差值。

rs.printSlaveReplicationInfo() 返回的 delay 是什么单位?
这个 delay 值单位是**秒**,不是毫秒或分钟。它表示从节点(secondary)当前应用的 oplog 时间戳,距离主节点(primary)最新 oplog 时间戳的差值。注意:这是“逻辑延迟”,不是网络 RTT,也不是复制队列积压时长。
- 如果显示
delay: 0,不代表完全实时——可能刚追上,也可能因 oplog 写入间隔短而暂时为 0 - 若长期 >5 秒,需排查 secondary 负载、磁盘 I/O、oplog 大小是否过小
- 该值在
rs.printSlaveReplicationInfo()输出中紧挨着syncedTo时间显示,例如:delay: 3 secs
为什么 rs.printSlaveReplicationInfo() 显示延迟为 0,但实际查询却读不到新数据?
因为 rs.printSlaveReplicationInfo() 只反映 oplog 应用进度,不保证你发起的读请求一定落到已同步完成的节点上。常见原因:
- 读偏好(
readPreference)设为primaryPreferred或secondaryPreferred,但 driver 实际路由到了尚未应用完的 secondary - 应用层没显式指定
readConcern: "majority",导致读到未被多数节点确认的写入 - secondary 正在执行慢查询或 compact,短暂阻塞 oplog 应用线程(MongoDB 6.0+ 中更明显)
验证方式:在 secondary 上直接连进 shell,执行 db.adminCommand({replSetGetStatus: 1}),看 members[n].optimeDate 和 members[0].optimeDate(primary)的差值。
rs.printSlaveReplicationInfo() 不显示某个 secondary?
说明该节点当前未被 primary 视为有效同步源——最常见原因是它处于 STARTUP2、RECOVERING 或 ARBITER 状态,或者心跳失败超时(默认 10 秒)。
- 检查
rs.status().members中对应节点的stateStr字段,常见异常值:DOWN、UNKNOWN、ROLLBACK - 确认该节点能否 ping 通 primary 的端口,且
bindIp配置允许跨主机连接 - 如果节点刚重启,可能还在 initial sync 阶段,此时
rs.printSlaveReplicationInfo()默认忽略它(只显示状态为SECONDARY的成员)
替代方案:比 rs.printSlaveReplicationInfo() 更准的延迟观测方式
rs.printSlaveReplicationInfo() 是 shell 封装命令,底层调用 replSetGetStatus,但它的延迟计算逻辑较粗略。生产环境建议用以下方式交叉验证:
- 在每个 secondary 上运行:
db.runCommand({replSetGetStatus: 1}).members.find(m => m.stateStr === "SECONDARY").optimeDate,再与 primary 的optimeDate手动比对 - 通过
db.printSecondaryReplicationInfo()(旧版别名,行为一致)无实质区别,不必替换 - 监控采集应以
replSetGetStatus返回的optimeDate和lastHeartbeatRecv为准,避免依赖 shell 格式化输出
真正麻烦的是 oplog 跨时间窗口截断或 secondary 长期落后触发 re-sync —— 那时候 rs.printSlaveReplicationInfo() 可能干脆不显示它,得翻日志找 repl 模块的 Starting rollback 或 Not starting an oplog collection scan 提示。










