slavedelay生效需同时满足hidden: true、votes: 0和slavedelay为正整数,且仅对不参与选举和客户端访问的secondary有效;动态修改必须rs.remove()+rs.add(),oplog需覆盖延迟时长,真实延迟受网络与回放影响。

slaveDelay 必须和 hidden: true + votes: 0 一起用,否则可能升主
只设 slaveDelay: 3600 不起作用,MongoDB 会照常实时同步。真正触发延迟的是 slaveDelay 参数本身,但它只对「不参与选举、不被客户端访问」的 secondary 生效。常见错误是只配 priority: 0,结果节点状态变成 PRIMARY,误删数据立刻写入——这不是延迟失败,是根本没防住。
必须同时满足三项:
-
hidden: true:让该节点不出现在连接字符串里,应用无法读写 -
votes: 0:确保它不参与选举投票(priority: 0不够,仍可能因票数变化意外当选) -
slaveDelay值为整数秒(0–31536000),且仅在rs.add()时一次性声明
不能用 rs.reconfig() 动态修改 slaveDelay,必须 rs.remove() + rs.add()
MongoDB 明确拒绝运行中修改 slaveDelay,执行 rs.reconfig() 会报错:Cannot modify slaveDelay on a running member。想改延迟时间?只能先移除再重建。
操作顺序很关键:
- 先
rs.remove("backup-node:27017") - 再
rs.add({ host: "backup-node:27017", priority: 0, votes: 0, hidden: true, slaveDelay: 7200 }) - 等待该节点完成 initial sync,进入
SECONDARY状态后,slaveDelay才开始计时
别指望改完配置就立刻“慢一小时”,它得先把全量数据拉完,才开始按 oplog 时间戳往后拖。
oplog 容量必须覆盖 slaveDelay 设定值,否则复制中断
slaveDelay 不是凭空延迟,它靠回放 oplog 实现。如果副本集 oplog 太小(比如只保留 30 分钟),而你设了 slaveDelay: 3600(1 小时),该节点会卡在 “oplog gap” 状态,无法继续同步,rs.status() 中显示 STARTUP2 或 RECOVERING,永远进不了 SECONDARY。
检查与扩容方法:
- 查当前 oplog 大小:
db.getReplicationInfo()看maxSize和timeDiff - 扩容 oplog 需停机:删除
local.oplog.rs集合并重建,指定更大size(单位字节) - 经验公式:oplog 至少保留
slaveDelay + 2 小时的写入量,避免高峰期被冲掉
真实延迟 ≠ slaveDelay 值,别依赖它做精确时间窗口
设置 slaveDelay: 3600,不代表你能稳稳抢救 3600 秒。真实延迟 = slaveDelay + 网络传输耗时 + oplog 回放耗时。尤其当主库批量写入或从节点 IO 跟不上时,db.printSecondaryReplicationInfo() 显示的“落后秒数”可能远大于 3600。
更要紧的是:它防不了所有误操作。
- 对
deleteMany({})、updateMany这类写入型误操作,有缓冲作用 - 但
dropDatabase()、dropCollection()同样会被复制,只是晚一小时到达——你得在那一小时内发现、停掉同步、导出数据 - 它不是备份替代品,不能恢复到某个时间点,也不能防止硬件故障或主库误删后未及时干预
最易被忽略的一点:延迟节点的数据快照是“固定滞后”的,它本就不该提供最新视图。如果你的应用误连上去读取,会以为数据丢了——其实只是设计如此。











