hidden 和 priority: 0 必须同时设置才能确保节点真正只读,仅 hidden: true 不足以阻止其参选;报表服务需 directConnection=true 直连,且 hidden 节点应差异化配置 slaveDelay 并谨慎管理 votes。

hidden + priority: 0 必须同时设置,缺一不可
只设 hidden: true 而不设 priority: 0,节点仍可能被选为 primary——因为 hidden 仅影响客户端发现逻辑,不干预选举资格。MongoDB 的选举决策只看 priority 值,只要 > 0,哪怕 hidden,它在其他节点宕机时仍会参选。这会导致报表节点意外接管写入,破坏只读语义。
常见错误配置:rs.add({ host: "report-1:27017", hidden: true }) ✅ 隐藏了,但 ❌ 可能变主rs.add({ host: "report-1:27017", hidden: true, priority: 0 }) ✅ 真正只读
注意:votes: 0 和 priority: 0 不等价:
- votes: 0 仅取消投票权,不影响是否可被选为 primary
- priority: 0 才真正禁止参选,是只读保障的硬性前提
报表服务必须用 directConnection=true 直连,禁用副本集发现
即使节点已配置 hidden: true,若客户端使用副本集连接串(如 mongodb://node1:27017,node2:27017,report-1:27017/?replicaSet=rs0),驱动仍可能通过心跳探测到该节点,并在 readPreference=secondary 下尝试路由——尤其旧版 Java/Python 驱动存在此行为。
正确做法是:报表服务只连单节点 URI,并显式启用 directConnection=true:
✅ mongodb://report-1:27017/?directConnection=true
❌ mongodb://report-1:27017/?replicaSet=rs0(触发自动发现)
❌ mongodb://node1:27017,node2:27017,report-1:27017/?replicaSet=rs0(暴露 hidden 节点)
PyMongo 示例:MongoClient("mongodb://report-1:27017", directConnection=True)
不是 MongoClient("mongodb://report-1:27017", replicaSet="rs0")
多个 Hidden 节点需差异化 slaveDelay,避免同步风暴
所有 Hidden 节点默认从 primary 拉取 oplog,若 slaveDelay 值相同(比如都设为 3600),它们会在同一时刻发起批量拉取请求,造成主节点 CPU 和网络瞬时尖峰,拖慢线上写入。
建议按用途错开延迟值,最小间隔 ≥ 300 秒:
- 报表专用节点:"slaveDelay": 300(5 分钟,兼顾时效与负载)
- 备份专用节点:"slaveDelay": 86400(24 小时,完全隔离)
- 恢复验证节点:"slaveDelay": 3600(1 小时,用于流程测试)
注意:
- slaveDelay 单位是秒,必须为整数
- 修改后需执行 rs.reconfig() 生效,该操作会触发一次选举,务必避开业务高峰
- 不要依赖 readOnly: true 或 fsyncLock():前者对远程连接无效,后者在 4.2+ 已废弃且全局阻塞
隐藏节点仍可投票,需确保副本集多数可用
hidden: true 不影响投票权,默认 votes: 1。如果停掉一个有投票权的 Hidden 节点,又恰好其他节点也宕机,可能导致副本集失去多数(majority),primary 主动降级,整个集群只读。
安全做法:
- 若不需要 Hidden 节点参与投票,显式设 votes: 0,但必须同步确认副本集剩余成员仍满足多数(例如三节点副本集,至少需两个 votes: 1 成员)
- 永远不要把所有 votes: 1 的节点都设为 hidden,否则选举机制失效
- 在分片集群中,mongos 无法访问 Hidden 节点;报表服务必须直连,不能走路由层
最容易被忽略的一点:Hidden 节点的 bind_ip 和认证配置必须和主节点一致——如果漏配 security.authorization: enabled 或误开 bind_ip: 0.0.0.0,可能让报表节点成为未授权写入入口。



















