non-voting节点是mongodb副本集中不参与选举投票、不影响法定人数计算但同步oplog并存储数据的成员,适用于跨城容灾备份或低配机器部署;需设votes:0且priority:0,常配hidden:true避免客户端误读。

什么是Non-Voting节点及其适用场景
Non-Voting节点是副本集里不参与选举投票、也不影响法定人数(quorum)计算的成员,但它仍会同步oplog、保持数据最新。它适合部署在容灾机房或低配机器上——比如跨城异地机房只做数据备份、不承担主节点切换职责;或者某台服务器资源紧张,又不想让它干扰选举逻辑。
注意:它和arbiter不同,arbiter不存数据、只投票;Non-Voting节点存数据、但不投票。
- 必须设置
votes: 0和priority: 0(否则违反MongoDB约束) - 不能是唯一能提供最新数据的节点(否则选举可能卡住)
- 建议搭配
hidden: true避免客户端意外读到它(除非你明确需要从该节点读)
配置Non-Voting节点的具体步骤
以将 192.168.10.44:27017 加入副本集并设为Non-Voting为例:
先确认当前配置:cfg = rs.conf()printjson(cfg.members)
再添加新成员(假设它是第3个,即索引 2):cfg.members[2] = { _id: 2, host: "192.168.10.44:27017", votes: 0, priority: 0, hidden: true }
最后重载配置:rs.reconfig(cfg, { force: true })
⚠️ 关键点:
– 必须同时设 votes: 0 和 priority: 0,否则 rs.reconfig() 会报错:"cannot have votes > 0 and priority == 0" 或 "non-voting member must have priority 0"
– 如果副本集只有3个节点,加一个 votes: 0 节点后,法定人数仍是 2(即多数派 = ⌊3/2⌋ + 1),不影响可用性;但如果原只有2个投票节点,加完这个节点后总投票数仍为2,就达不到多数派(需 ≥2),此时集群写入会失败
为什么Non-Voting节点不能提升选举稳定性?
很多人误以为加Non-Voting节点能“增强容灾能力”,其实它对选举过程完全无贡献。选举只看投票节点(votes > 0)是否构成多数派、心跳是否正常、oplog是否足够新。
真正影响选举稳定性的因素包括:
– 投票节点数量是否为奇数(避免脑裂)
– electionTimeoutMillis 设置是否合理(默认10秒,高延迟网络建议调大)
– 所有投票节点的 priority 是否差异化(避免平票)
– slaveDelay 或 hidden 节点是否被误设为投票节点
所以,Non-Voting节点只解决“数据多一份、不参与决策”的问题,不是选举兜底方案。
常见错误:rs.reconfig() 失败后状态混乱怎么办
如果执行 rs.reconfig() 出错(如参数冲突、版本不兼容、网络中断),副本集可能进入 STARTUP2 或 REMOVED 状态,部分节点无法同步。
应急操作顺序:
– 在 PRIMARY 上运行 rs.status() 确认哪些节点状态异常
– 检查日志中最近的 reconfig 错误详情(关键词:reconfig failed, not majority, priority/votes conflict)
– 回退配置:用 cfg = rs.conf() 取出旧配置,手动修正后再次 rs.reconfig(cfg)
– 若 PRIMARY 已不可用,且剩余投票节点不足多数,只能人工介入:停止所有节点 → 清理 dbpath 下的 local.* 文件 → 用原始配置重新 rs.initiate()
最易被忽略的一点:MongoDB 5.0+ 对 rs.reconfig() 的校验更严格,比如不允许在非PRIMARY节点上执行,也不允许在 rs.status().members[n].stateStr === "STARTUP" 时修改该节点配置。











