副本集选举失败的首要原因是votingMembers数量不足多数,即在线投票节点数≤⌊N/2⌋,此时选举根本不会启动;需通过rs.status()检查votes、stateStr、optimeDate、health等字段定位问题。

rs.status() 显示 votingMembers 少于多数,选举直接失败
副本集选举启动的前提是:至少有 (N/2 + 1) 个具备投票权的节点在线且能互相心跳。如果当前在线的 voting 成员数 ≤ ⌊N/2⌋,选举根本不会发起——不是“选不出来”,而是“连投票资格都不满足”。常见于 3 节点集群挂掉 2 个、或误将多个节点设为 v: 0 后只剩 1 个投票节点。
实操建议:
- 立即运行
rs.status(),检查members[n].stateStr和members[n].votes字段,确认哪些节点实际在参与投票 - 注意
arbiterOnly: true的仲裁节点也算作 1 票,但不存数据;它必须在线且网络可达 - 若发现本该有投票权的节点显示
"v" : 0,说明被手动禁用了投票权(比如配置了priority: 0且未显式设v: 1),需通过rs.reconfig()恢复 - 2 节点复制集天然不满足多数原则,必须加仲裁节点(
rs.addArbiter()),否则任意一节点宕机即服务中断
节点状态为 STARTUP 或 RECOVERING,无法参与选举
刚启动或刚完成初始同步的节点,状态不是 SECONDARY,而是 STARTUP、RECOVERING 或 ROLLBACK。这些状态下的节点不响应选举请求,也不投自己或他人一票——即使它配置了 v: 1 和高 priority。
实操建议:
- 用
rs.status().members[n].stateStr逐个确认状态;RECOVERING通常意味着 oplog 同步卡住或磁盘 I/O 延迟高 -
STARTUP状态持续超 30 秒,检查 mongod 日志里是否有Failed to load metadata或权限错误 - 避免在节点处于
RECOVERING时强制rs.reconfig(),可能触发配置回滚
oplog 落后超 10 秒,节点被自动排除在选举外
MongoDB 不会把一个 oplog 时间戳(optime)比多数节点落后超过约 10 秒的节点选为 Primary——哪怕它 priority=1000。这是防止脑裂和数据回滚的关键保护机制。你看到某个节点状态是 SECONDARY、v: 1、priority: 5,但它始终没被选上,大概率是 optimeDate 比其他节点旧太多。
实操建议:
- 对比
rs.status().members[n].optimeDate,找出时间最旧的那个节点 - 若落后明显(如 >60 秒),先查该节点的复制延迟日志:
db.printSlaveReplicationInfo() - 不要直接 kill mongod 强制重同步;优先尝试
rs.syncFrom("target_host:port")指定一个新源 - 若 oplog 已被主节点覆盖(出现
StaleConfig或OplogStartMissing错误),只能删数据目录重启,走完整初始同步
心跳超时导致多数派失联,选举被阻断
默认心跳超时是 10 秒(heartbeatTimeoutMillis: 10000)。如果网络抖动、防火墙拦截或系统负载过高,导致连续 5 次心跳失败(即 50 秒内无响应),节点会被标记为 DOWN。此时即使物理机器活着,也会被集群视为离线,进而破坏多数派条件。
实操建议:
- 检查
rs.status().members[n].health,值为 0 表示心跳失败;再看lastHeartbeat时间戳是否陈旧 - 临时调高超时阈值(仅限排查期):
rs.reconfig(cfg, {force: true})中加入settings.heartbeatTimeoutMillis: 30000 - 生产环境更推荐加固网络:关闭中间设备的连接空闲超时、避免跨公网部署副本集、禁用 TCP SACK(某些内核版本下引发心跳丢包)
votingMembers 数量没过半,选举就永远不会开始——这点最容易被监控脚本忽略。


















