MongoDB 4.0+ 已移除 rs.addArb(),必须用 rs.add({host: "h:p", arbiterOnly: true}) 在主节点执行;仲裁节点仅投票、不存数据,需跨故障域部署并验证 rs.status() 中 stateStr 和 health。

rs.addArb() 不能直接加仲裁节点,必须用完整配置对象
很多人执行 rs.addArb("host:27017") 报错 no such cmd: addArb 或 not master,根本原因是:MongoDB 从 4.0 开始已移除独立的 rs.addArb() 命令,它从来就不是“函数”,而是 rs.add() 的语法糖——且仅在旧版本(≤3.6)中存在。现在必须显式传入带 arbiterOnly: true 的配置对象。
- 正确写法:
rs.add({host: "arbiter.example.com:27017", arbiterOnly: true}) - 错误写法:
rs.addArb("arbiter.example.com:27017")(命令不存在) - 必须在主节点(primary)上执行,且该节点状态为
PRIMARY(可用rs.status().myState确认) - 仲裁节点主机必须能被所有副本集成员通过 hostname 解析并建立 TCP 连接(端口 27017 默认)
仲裁节点不存数据,但对选举权重和故障域有实际影响
仲裁节点(arbiter)只参与投票,不复制数据、不服务读请求、不占用磁盘空间——听起来是“零成本高可用”,但它的加入会实质性改变选举逻辑和容错边界。
- 副本集总票数 = 数据节点票数 + 仲裁节点票数(默认各为 1),必须 > 总票数一半才能选出 primary;加 1 个 arbiter 可让 2 节点集群具备故障转移能力(2+1=3 票,允许 1 节点宕机)
- 但若把 arbiter 和某个数据节点部署在同一物理机或同一可用区,等于没扩大故障域——网络分区时可能同时失联,反而降低可用性
- 仲裁节点的
priority始终为 0,无法被设为 hidden / delayed,也不能配置tags;这些字段传了也会被忽略
添加后需验证状态,常见失败场景有三类
执行 rs.add(...) 返回成功不代表仲裁节点已生效。必须立刻检查 rs.status() 输出中的 members[n].stateStr 和 health 字段。
-
"stateStr": "ARBITER"且"health": 1→ 正常 -
"stateStr": "DOWN"→ 网络不通或目标端口未监听(确认mongod是否运行、bindIp是否包含该网卡、防火墙是否放行) -
"stateStr": "REMOVED"→ 被自动踢出,通常因心跳超时(默认 10 秒),可临时调大heartbeatTimeoutSecs(不推荐长期使用) - 如果
rs.status()中看不到新成员,可能是配置未持久化——检查rs.conf().members是否已更新;若没更新,说明rs.add()执行失败但未报错(罕见,多因权限不足或 config server 模式误用)
低成本架构下,仲裁节点不是万能解,要防单点依赖反模式
用 1 个数据节点 + 1 个仲裁节点撑起“高可用”看似省事,但实际是伪高可用:一旦数据节点宕机,整个集群不可写;仲裁节点宕机虽不影响服务,但会让剩余节点失去多数票,下次数据节点故障时无法自动选举。
- 真正低成本可靠方案是:2 数据节点 + 1 仲裁节点(跨机房/可用区部署),或直接用 3 个数据节点(无仲裁,读写分离更灵活)
- 仲裁节点不能替代备份——它不存数据,崩溃后无法恢复任何历史状态
- 监控必须覆盖
rs.status().members[n].lastHeartbeatRecv,比单纯 ping 端口更能反映真实连通性


















