根本原因是投票节点数不足多数派,即votes:1的在线节点数未达N/2+1;需用rs.status().members.filter(m=>m.votes===1&&m.state<=2).length确认有效投票节点数。

为什么 rs.status() 显示多数节点 offline,却 still no Primary
根本原因就一条:votes: 1 的节点数不够形成“大多数”。MongoDB 不看物理节点总数,只看有投票权(votes: 1)的成员是否达到 N/2 + 1——这里的 N 是所有 votes: 1 成员的数量,不是你启动的 mongod 进程数。
常见误判场景:
- 误把
arbiter当成普通节点:它votes: 1但priority: 0,不存数据、不参与 oplog 同步,只投一票——但它算进N,也计入“大多数”分母 - 手动设过
votes: 0却忘了:比如为某个延迟从库关掉投票权,那它既不参选也不投票,直接被踢出选举公式 - 节点状态是
STARTUP2或RECOVERING:这类节点心跳正常,但 MongoDB 认为它“尚未准备好”,不纳入投票池,也不给它发选票
查真实投票成员数:
rs.status().members.filter(m => m.votes === 1).length
再查当前在线且可投票的成员数:
rs.status().members.filter(m => m.votes === 1 && (m.state === 'PRIMARY' || m.state === 'SECONDARY')).length
两者对比,差值就是卡住选举的缺口。
rs.reconfig() 后选举卡在 “waiting for majority” 怎么办
执行 rs.reconfig() 时如果当前存活的 votes: 1 节点数
紧急恢复必须加 {force: true},但要注意:
- 只能连当前
PRIMARY执行;连SECONDARY会报NotMaster -
{force: true}绕过“多数在线”校验,但不绕过“心跳可达”——目标节点仍需能和至少一个其他votes: 1成员通信 - 强制重配后,原 Primary 可能立刻
stepDown,写入中断 3–8 秒,别在金融类事务高峰干这事
典型操作链:
cfg = rs.conf(); cfg.members[2].priority = 5; cfg.members[2].votes = 1; rs.reconfig(cfg, {force: true})
Arbiter 没了,3 节点集只剩 2 个 Secondary,还能选主吗
不能。3 节点副本集标准配置是 2 个 Secondary + 1 个 Arbiter,此时 N = 3(两个 Secondary 各 votes: 1,Arbiter 也 votes: 1),需要 2 票才能当选。
Arbiter 挂掉后,剩下两个 votes: 1 的 Secondary,但它们互相投票最多各得 1 票——谁也凑不够 2 票。系统进入只读,rs.status().ok 仍为 1,但 primary 字段为空。
临时解法只有两个:
- 重启 Arbiter,或用新机器补一个(注意 host:port 必须和
rs.conf()里完全一致) - 连 Primary 执行
rs.reconfig(),把其中一个 Secondary 的votes改成 0,让N变成 2 → 多数变成 2 → 剩下一个votes: 1的 Secondary 自动获全票当选(但失去容错能力,仅限救火)
真正健壮的部署,从来不用 Arbiter 撑多数——3 节点就全配 votes: 1,5 节点里最多只放 1 个 Arbiter,否则网络抖动一次就失写。
oplog 落后太多导致节点被跳过选举,怎么确认
选举时不光比 priority,更关键的是比 optime(即 oplog 最后一条时间戳)。一个 priority: 10 的节点,如果 optime 比 Primary 落后超 10 秒,默认就被视为“数据太旧”,其他节点不会投它。
查同步差距:
rs.printSecondaryReplicationInfo()
看输出里 syncedTo 和当前时间差多少秒。差值 >10s 就危险;>60s 基本无缘参选。
快速判断法:
- 该节点
stateStr是SECONDARY,但lastHeartbeatRecv时间戳停滞不动 → 网络或复制线程卡死 -
optimeDate比rs.status().members[0].optimeDate(Primary 的)慢超过 30 秒 → 已被选举逻辑静默排除
修复不是调高 priority,而是先解决复制延迟:检查磁盘 I/O、网络带宽、oplogSize 是否过小、是否有大文档批量写入阻塞复制线程。


















