catchup阶段是新主节点在正式接管写入前必须完成的oplog同步过程,发生在获多数票后、标记为primary前,确保复制并应用所有可获取oplog条目,防止数据丢失与因果链断裂。

什么是Catchup阶段:主节点当选前必须完成的日志追平
Catchup阶段不是选举的“开始”,而是新主节点在正式接管写入前,强制完成的oplog同步过程。它发生在节点被提名参选(或已获多数票)之后、但尚未标记为PRIMARY之前——此时该节点必须确保自己已复制并应用完所有可获取的oplog条目,否则拒绝升主。这是MongoDB防止数据丢失的关键防线。
replSetStepDown触发的Catchup阶段最容易被误判为“卡住”
执行rs.stepDown()后,原主降级,其他节点启动选举;但若某个候选节点oplog落后较多(比如延迟超60秒),它会在投票通过后先进入CATCHUP状态,而不是直接变PRIMARY。这时rs.status()里能看到该节点状态是"stateStr" : "CATCHUP",而非"PRIMARY"或"SECONDARY"。
- 常见错误现象:
rs.status()显示某节点状态长期卡在CATCHUP,日志里反复出现waiting for oplog to catch up before stepping up - 根本原因:该节点的oplog尾部时间戳比当前主节点的
lastApplied晚太多,而catchUpTakeover机制要求它先追平才能升主 - 参数影响:
rs.stepDown(60, 30)中第二个参数catchUpSecs就是为此预留的追赶窗口——若30秒内追不平,该节点会主动放弃本次升主尝试 - 别硬等:如果oplog差距过大(例如从节点宕机数小时),Catchup可能永远无法完成;应先检查
rs.printSlaveReplicationInfo()确认延迟值,再决定是否手动rs.syncFrom()切换同步源加速追赶
为什么不能跳过Catchup:WiredTiger引擎下oplog截断的真实风险
Catchup不是性能优化项,而是数据一致性强制门槛。WiredTiger存储引擎默认会定期截断旧oplog(由replSetResizeOplog或后台任务触发),一旦候选节点还没来得及拉取就被截掉,它就永远无法构造出完整的因果链——升主后写入将与集群其它节点产生不可逆的逻辑冲突。
- 典型后果:节点强行跳过Catchup(如通过非官方patch或绕过校验)后成为
PRIMARY,但随后出现OplogStartMissing错误,整个副本集进入只读不可恢复状态 - 兼容性注意:该机制在4.2+全版本生效,且与
electionTimeoutMillis无关——缩短选举超时只会加快“谁来当主”的决策,不缩短“当主前要干啥” - 运维提示:
rs.printReplicationInfo()中的oldestTimestamp和latestTimestamp差值,就是当前oplog覆盖的时间窗口;确保所有节点的optimeDate都落在这个窗口内,否则Catchup必然失败
如何安全缩短Catchup耗时:用replSetSyncFrom换同步源比等原主更可靠
默认情况下,从节点从配置中syncSourceHost指定的节点拉oplog;但如果该源本身也在追赶、或网络质量差,就会拖慢整个Catchup。此时可人工干预同步目标,尤其推荐指向一个刚完成同步、延迟极低的Secondary。
- 实操命令:
rs.syncFrom("node2.example.com:27017")(在待升主节点上执行) - 关键限制:目标节点必须处于
SECONDARY或PRIMARY状态,且其lastApplied时间戳不能早于本节点当前lastApplied——否则命令会直接报错Cannot sync from node with older optime - 别忘清理:该设置是临时的,仅影响下一轮oplog拉取;一旦节点成功升主,
syncSourceHost会自动重置为配置中的默认值 - 陷阱提醒:切勿对仲裁节点(Arbiter)执行此命令,它不存oplog,
syncFrom会静默失败且不报错
真正难处理的从来不是Catchup本身,而是当它迟迟不结束时,你有没有第一时间去看rs.printSlaveReplicationInfo()里的延迟数字,而不是反复rs.stepDown重试。










