必须先调用rs.stepDown()让主节点安全降级为从节点,再停止服务;直接停进程会触发强制选举导致写入丢失。

不能直接停主节点进程,否则会触发强制选举,可能造成写入丢失或客户端短暂不可用;必须先让主节点降级为从节点,再停止服务。
如何安全地让主节点降级为从节点
核心是调用 rs.stepDown(),它会让当前主节点主动放弃主身份,触发一次受控选举。注意这不是立即生效——它会等待现有写操作完成,并默认阻塞 60 秒(防止频繁切换),期间该节点仍可读但拒绝写入。
- 连接到目标主节点的
mongoshell(或使用 MongoDB Compass 的 Shell 标签页) - 执行
rs.stepDown(30):传入 30 表示最多等待 30 秒,比默认更可控;若集群负载高、有长事务,可适当加长,但不建议超过 60 - 执行后立刻用
rs.status()观察:原主节点的stateStr应变为SECONDARY,且primary字段指向新主节点 - 如果返回
NotMaster错误,说明它已在降级过程中或已完成;若超时仍未降级,检查是否有未确认的写操作(db.serverStatus().metrics.repl.buffer可辅助判断)
为什么不能用 rs.freeze() 或直接 db.shutdownServer()
rs.freeze() 只是阻止节点在指定时间内参选,但它仍是主节点,仍接受写请求;一旦 freeze 时间结束或被手动解冻,它可能再次抢主,维护窗口不可控。db.shutdownServer() 是暴力终止,主节点进程一挂,剩余节点会在 10–30 秒内发起选举——这期间所有发往原主的写请求都会报 NotWritablePrimary,且未同步到多数节点的 oplog 可能丢失。
- freeze 适合做“防误切”保护,不适合主动下线流程
- shutdownServer 必须在
rs.stepDown()成功且确认状态为 SECONDARY 后才能调用 - 某些驱动(如 PyMongo)在连接串中配置了
readPreference=primary,降级后会自动重路由,但需确保应用层没硬编码直连原主 IP
下线前必须验证的三个状态点
跳过任一检查,都可能导致维护失败或数据异常。
- 新主节点的
optimeDate(通过rs.status().members[n].optimeDate)必须 ≥ 原主节点降级前的optimeDate,确保 oplog 已追平 - 原主节点的
lastHeartbeatRecv时间距今不超过 10 秒,说明它仍与集群网络连通,不是因分区被孤立 - 所有客户端连接已断开或完成重连——可通过
db.currentOp({secs_running: {$gt: 0}})检查是否有长运行操作残留
真正麻烦的不是命令本身,而是降级后那几十秒里 oplog 同步是否真实完成;很多问题出在误判“已降级成功”,其实从节点还没追上,就急着关进程。


















