仲裁节点(arbiter)设计上禁止存储数据,启动必须加--arbiterOnly参数,添加须用rs.add({host:..., arbiterOnly: true}),否则会误作数据节点卡在STARTUP2;它不参与读写、无oplog、不复制,仅提供选举投票。

仲裁节点(arbiter)根本不能存数据,不是配置没设对,而是设计上就禁止——它压根没有数据目录、不写oplog、不参与复制链。
Arbiter 启动时必须带 --arbiterOnly 参数
启动命令里漏掉这个参数,mongod 就会当成普通节点跑,试图初始化数据目录、加载 oplog、同步主节点数据——结果要么卡在 STARTUP2 状态不动,要么报 Failed to load metadata 错误。正确写法是:
mongod --port 27017 --dbpath /data/arbiter --replSet rs0 --arbiterOnly --bind_ip_all
注意:--arbiterOnly 是启动参数,不是配置文件里的字段;dbpath 虽然要指定,但实际不会被写入任何数据文件,只是占位用。
rs.add() 添加 arbiter 必须显式传 arbiterOnly: true
MongoDB 4.0+ 已彻底移除 rs.addArb() 命令,现在所有添加操作都走 rs.add(),但必须带完整配置对象:
- ✅ 正确:
rs.add({host: "arbiter.example.com:27017", arbiterOnly: true}) - ❌ 报错:
rs.addArb("arbiter.example.com:27017")(命令不存在) - ❌ 报错:
rs.add("arbiter.example.com:27017")(会被当普通节点加,后续无法修正)
加完后立刻执行 rs.status(),确认新节点的 stateStr 是 "ARBITER",且 infoMessage 为空;如果显示 "STARTUP2" 或 "RECOVERING",说明它正在尝试同步数据——那一定是配置错了。
Arbiter 不参与读写,客户端连接字符串里不该包含它
驱动(如 Node.js 的 mongodb)在解析副本集连接串时,会把所有节点地址都加入发现列表,但 arbiter 永远不会被选为写目标,也永远不会响应读请求(readPreference 设成 nearest 也不会路由过去)。更关键的是:
- 它不维护连接池,不处理任何 CRUD 命令,收到 insert/update 就直接返回
NotMaster - 如果连接串里硬写了 arbiter 地址(比如
mongodb://node1,node2,arbiter/mydb),某些旧版驱动可能因 DNS 解析失败或握手超时拖慢整个初始化过程 - arbiter 的健康状态不影响应用读写——它挂了,只要剩下节点票数仍过半,选举照常;但它连不上主节点,就会在
rs.status()里显示health: 0,误导你去排查“不可用”
为什么不能让 Arbiter 存数据?这和投票逻辑强绑定
arbiter 的唯一存在价值,是在偶数个数据节点时提供“第奇数票”,打破选举僵局。如果它也能存数据:
- 它的 oplog 无法跟上主节点(没复制逻辑),一旦被误选为 primary,立刻产生数据分裂
- 写关注
w: "majority"会把 arbiter 算进“多数”,但它的确认毫无意义——没数据、没持久化、没回滚能力 - 事务和分片键操作会直接失败,因为
mongos在预检阶段就拒绝含 arbiter 的分片参与两阶段提交
所以别琢磨“能不能给 arbiter 配个 storage.dbPath”,它连 storage 配置段都不认——这是内核级硬限制,不是文档没写全。


















