在 MongoDB 副本集中,成员优先级需要先通过rs.conf()取出当前配置,找到对应的members[n].priority后再进行调整,最后使用rs.reconfig(cfg)提交使配置生效,取值范围是0–1000。这里有一条硬性规则:priority=0的节点永远不能成为primary,而且还必须同时满足设为votes=0或hidden=true中的至少一项。另一个非常容易踩坑的地方也要提前说明——这类配置修改必须连接到当前primary执行,修改前一定先确认members的索引准确无误,避免把优先级配错到其他节点。

直接说结论:MongoDB副本集成员优先级的设置方法,就是先通过 rs.conf() 获取配置,修改 members[n].priority,再使用 rs.reconfig(cfg) 提交。priority 的取值范围是 0–1000,而 priority=0 的节点永远不能成为 primary。
连接到 primary 后才能修改 priority
必须连接到当前的 primary 节点后,才能修改 MongoDB 副本集成员的 priority,否则执行 rs.reconfig() 时会报错 not master。这是因为 secondary 节点默认是只读的,不接受副本集配置变更。
- 使用
mongo --host连接时,要先确认连接的是 primary,避免连错节点--port - 如果不确定哪个节点是 primary,可以先执行
rs.status(),查看stateStr字段为PRIMARY的成员 - 如果当前 primary 刚发生故障且新的 primary 还未选举出来,整个副本集会处于不可写状态,此时修改 priority 通常会失败
修改 members[n].priority 时最容易写错索引
members 数组下标是从 0 开始的,但这个下标和节点本身的 _id 并不是同一个概念,这也是设置副本集优先级时最常见的问题之一。
- 执行
cfg = rs.conf()之后,先打印cfg.members,确认目标节点位于第几个位置,例如host: "node3:27017"可能对应的是members[2] - 不要凭印象直接写
cfg.members[0].priority = 2,除非你已经明确确认过members[0]就是要调整优先级的那个节点 - 修改完成后务必再次检查:
cfg.members[2].host与cfg.members[2].priority是否符合预期
priority=0 的节点必须同时满足 votes=0 或 hidden=true
MongoDB 对副本集成员有明确限制:当节点的 priority 为 0 时,如果仍然保留 votes=1,执行 rs.reconfig() 时就会拒绝提交,并报错 cannot ha ve votes > 0 when priority is 0。
- 如果希望某个节点只承担备份任务、不参与 primary 选举,通常可以设置为
priority=0+hidden=true+votes=0 - 仲裁节点(arbiter)默认是
priority=0且votes=1,这是 MongoDB 允许存在的特例 - 如果误把普通 secondary 的
priority改为 0,但没有同步调整votes,那么配置会失败,需要回退后重新设置
rs.reconfig() 可能触发新的主节点选举
即使只是修改一个 priority 字段,MongoDB 也会认为副本集配置已经发生变化,因此可能让当前 primary 主动 stepDown,并触发一次新的选举——这不是 bug,而是副本集的正常设计行为。
- 选举期间通常会出现 10–20 秒左右的写入中断,客户端可能收到
NotPrimaryNoSecondaryOk或超时错误 - 因此不建议在业务流量高峰时调整优先级;如果系统对可用性要求非常高,可以提前使用
rs.stepDown()手动触发一次选举,先观察恢复耗时 - 修改完成后应立即执行
rs.status(),确认新的 primary 已成功就位,同时检查所有 secondary 的optimeDate是否没有明显落后
真正麻烦的地方,其实不是 MongoDB 副本集 priority 设置本身,而是修改完成后没有持续关注 rs.status() 输出中的 optimeDiffs 和 lastHeartbeatRecv。如果某个节点复制延迟过高或心跳异常中断,那么即使它的 priority 再高,也依然无法被成功选举为 primary。
