仲裁节点不存数据,仅参与选举投票以打破僵局;必须用rs.addArbiter()添加,确保replSet名一致、网络可达、DNS可解析,且不可与主节点同机部署。

仲裁节点不存数据,但能决定谁当主节点
仲裁节点(arbiter)本身不保存任何业务数据,也不提供读写服务,只参与选举投票。它存在的唯一目的,是在主节点宕机、剩余数据节点数为偶数时,打破投票僵局,确保副本集能选出新主节点。所以别指望它分担读压力或备份数据——它就是个“举手投票的裁判”。
常见错误现象:rs.status() 显示 "stateStr" : "ARBITER",但应用连接时反复报 NotMasterNoSlaveOk 或超时;或者添加后副本集状态卡在 STARTUP2 不动。
- 必须用
rs.addArbiter()添加,不能用rs.add()加普通节点再改配置——后者会失败并留下脏状态 - 仲裁节点的
host必须能被所有数据节点通过 DNS 或 hosts 解析通,否则心跳失败,直接被踢出集群 - 不要把仲裁节点和主节点部署在同一台物理机或同一可用区——它本该提升容灾能力,而不是放大单点风险
怎么加一个仲裁节点:三步走,少一步都选不出主
加仲裁节点不是“启动 mongod 就完事”,关键在初始化阶段的配置对齐。最常踩的坑是:mongod 进程启动了,但没进副本集,或者进了但端口/域名没对上。
实操顺序:
- 在目标机器上启动 mongod,**必须带
--replSet参数且值与现有副本集名完全一致**,例如:mongod --replSet rs0 --port 27017 --bind_ip localhost - 连上任意一个已有数据节点,在 shell 里执行:
rs.addArbiter("arbiter-host:27017")—— 注意这里填的是仲裁节点的可访问地址,不是localhost(除非所有节点都在本机) - 立刻执行
rs.status(),确认新节点出现在数组里,且stateStr是ARBITER,health是1
如果卡在 RECOVERING 或 UNKNOWN,大概率是网络不通或 replSet 名不一致;rs.conf() 里检查 members[n].arbiterOnly: true 是否已自动设为 true。
仲裁节点挂了会影响读写吗?会影响选举吗?
不影响读写,但可能影响下一次选举能否成功。只要当前主节点活着、多数数据节点在线,应用完全无感。但一旦主节点宕机,而剩下的数据节点数是偶数(比如 2 个),没有仲裁节点投关键一票,选举就会失败,整个副本集降级为只读。
性能与兼容性影响很小:仲裁节点内存占用极低(通常
- 删除仲裁节点用
rs.remove("arbiter-host:27017"),不是rs.stepDown() - 如果副本集只有 1 个数据节点 + 1 个仲裁节点,这种配置合法但极度危险:数据节点一挂,整个集就不可写,且无法自动恢复主节点
- 生产环境建议至少 3 个数据节点,或 2 数据节点 + 1 仲裁节点(仅限资源受限场景)
为什么 rs.addArbiter() 报错 “already initialized” 或 “node already exists”
这两个错误本质都是配置冲突:要么你试图往一个已经初始化过的副本集里重复加同一个地址,要么 mongod 实例本身已作为成员加入过其他副本集(比如测试环境残留的 local.system.replset 数据)。
解决路径很直接:
- 先查
rs.conf()输出,确认目标地址是否已在members数组中出现 - 如果出现,用
rs.remove("xxx")清掉旧记录,再重试rs.addArbiter() - 如果 mongod 是全新启动但依然报错,停掉进程,删掉它的
dbpath下的_mdb_catalog.wt和WiredTiger相关文件(保留数据文件前提下重置复制状态),再重启
最容易被忽略的一点:仲裁节点的 host 字段一旦写进配置,后续所有节点都按这个字符串去连它。如果填了 127.0.0.1,其他节点就会尝试连自己本地的 27017,而不是你本意的那台机器。

















