mongodb副本集自动故障转移需正确配置角色、投票权和心跳参数;初始化必须显式传入完整成员列表;优先级与投票权须匹配;客户端连接须启用重试和读偏好;选举超时建议调至5秒并验证生效。

能自动故障转移,前提是副本集配置正确——不是光靠“启动多个节点”就行,关键在角色、投票权和心跳参数的协同。
副本集初始化必须带完整成员列表
只用 rs.initiate() 不带参数,会创建单节点副本集,根本无法选举。必须显式传入所有成员的 host 和唯一 _id:
rs.initiate({
_id: "rs0",
members: [
{ _id: 0, host: "node1:27017", priority: 1 },
{ _id: 1, host: "node2:27017", priority: 0.5 },
{ _id: 2, host: "node3:27017", arbiterOnly: true }
]
})
- 缺任意一个
host或漏掉_id,后续rs.add()可能失败或导致状态不一致 -
arbiterOnly: true的节点不能同时设priority: 0,MongoDB 会忽略后者 - 所有节点必须使用相同
--replSet rs0启动参数,否则拒绝加入
优先级和投票权必须匹配实际部署意图
优先级(priority)决定谁更可能当选主节点,但投票权(votes)决定谁有资格参与选举——两者不一致就会卡住选举。
- 仲裁节点必须设
votes: 1(默认),且priority: 0;否则它既不能参选又不能投票,形同虚设 - 隐藏节点(
hidden: true)若未同步完成,priority再高也进不了选举池 - 所有数据节点的
votes必须为 1,哪怕你只想要它当备份;设成 0 就等于主动退出集群决策
客户端连接字符串必须启用重试和读偏好
服务端能自动切主,不代表应用能立刻跟上——连接层不配合,写操作仍会报 PrimaryUnavailable 错误。
- 连接串里必须加
retryWrites=true&retryReads=true,否则驱动不会在主节点切换后重试 - 读操作建议用
readPreference=secondaryPreferred,避免所有读请求都压到新主上造成抖动 - Laravel 等框架需确认
setRetryWrites(true)调用发生在连接建立后,而非配置文件里静态设置
心跳和选举超时参数不能依赖默认值
默认 electionTimeoutMillis=10000 意味着主节点宕机后最多要等 10 秒才开始选举——对多数业务来说太长。
- 生产环境建议调低至
5000(5 秒),通过rs.reconfig()修改:settings: { electionTimeoutMillis: 5000 } - 同时检查网络延迟:若节点间
PingMs> 2000ms,heartbeatIntervalMillis应同步调大,否则频繁误判离线 - 修改后必须运行
rs.status()验证settings.electionTimeoutMillis已生效,旧配置可能缓存
最常被忽略的是:故障转移后,旧主节点恢复时若未及时同步 oplog,可能因数据陈旧被踢出副本集——务必检查 optimeDate 是否落后太多,必要时手动执行 rs.syncFrom() 指定同步源。











