正常重启(保留dbPath和完整oplog)几秒内恢复SECONDARY;仅当dbPath清空、oplog断裂或配置重置时触发耗时initial sync,其瓶颈在于WiredTiger缓存冷启动导致IO等待高、CPU低,需预热或扩容oplog避免反复重同步。

重启后同步时间取决于是否触发 initial sync
不是所有重启都会导致长时间同步。只有当节点重启时 dbPath 被清空、或 oplog 历史断裂(比如被覆盖)、或副本集配置重置,才会进入 initial sync 阶段——这才是耗时数小时甚至一两天的根源。正常重启(保留 dbPath 和完整 oplog)通常几秒内就恢复 SECONDARY 状态。
- 检查是否在 initial sync:
rs.status().members[n].stateStr显示STARTUP2或RECOVERING,且rs.printSlaveReplicationInfo()中无延迟值(或显示not syncing) - 确认 oplog 是否连续:在 primary 上运行
db.getReplicationInfo(),看timeDiffHours是否 ≥ 你上次重启前的同步窗口;若远小于 1 小时,secondary 很可能因 oplog 覆盖被迫重同步 - 避免误删
dbPath:运维脚本或部署工具自动清理目录时,若没跳过dbPath,就会强制走 initial sync
initial sync 慢的核心瓶颈是 WiredTiger cache 冷启动
即使磁盘带宽充足,重启后 initial sync 仍卡在“IO wait 高、CPU 低”状态,本质是 WiredTiger cache 全空,所有数据页都要从磁盘 page fault 加载。尤其扫描大集合时,随机读放大严重,iowait 持续 90%+ 是典型表现。
- 默认 cache 大小为物理内存 50%,但重启即清空——无法复用旧缓存
- 预热方案有限:可用
mongodump --out /dev/null对全库做顺序扫描,强制提前加载热点页;或用find /path/to/dbPath -name "*.wt" -exec dd if={} of=/dev/null bs=1M count=1 \;触发文件预读(仅对 ext4/xfs 有效) - 企业版支持基于文件拷贝的 initial sync(
copyFilesFromPrimary),跳过逻辑克隆阶段,但社区版不可用
Oplog 大小不足会反复触发 initial sync
很多“重启后同步慢”的真实原因是:节点刚追上,oplog 就被覆盖,它立刻断连并重新 initial sync——形成恶性循环。这不是重启本身的问题,而是 oplog 窗口太窄。
- 查当前窗口:
db.getReplicationInfo().timeDiffHours,低于 2 小时就危险 - 扩容命令(4.4+):
db.adminCommand({replSetResizeOplog: 1, size: 20480})(单位 MB,建议按写入峰值 × 48 小时估算) - 旧版本(≤4.2)必须停机重建 oplog:关 secondary →
rm -f local/oplog.rs→ 启动 → 等它自己 initial sync → 再对 primary 执行同样操作(风险极高,慎用) - 别碰
numInitialSyncAttempts:它只控制 initial sync 失败后的重试次数,不提速
延迟节点(delayed member)重启后同步时间更长
如果你的节点配置了 slaveDelay(比如设为 3600 秒),它重启后不仅要完成 initial sync,还要额外“等满延迟时间”才开始应用 oplog。此时 optimeDate 与 primary 的差值会稳定在设定延迟值附近,不是故障。
- 确认是否为延迟节点:
rs.conf().members[n].slaveDelay返回非零值 - 延迟节点的
priority必须 ≤ 0,否则配置不生效 - 这种节点无法用于
w: "majority"写关注——它的数据天然滞后,不能参与法定人数计算
rs.status() 状态字和 db.serverStatus().metrics.repl 里的 apply 队列,再查 oplog 窗口和 cache 使用率。冷 cache + 小 oplog + 延迟配置三者叠加,会让一次普通重启变成半日工程。


















