hidden: true 节点不参与选举且对客户端不可见,不会出现在 rs.status() 中,也不被驱动自动路由;必须直连访问,需配合 priority: 0,仍同步数据但不计入延迟统计。

设置 hidden: true 后节点不参与选举但还能被读取?
不是。设了 hidden: true 的节点默认连 rs.status() 都不会显示在主节点的视图里,更不会被客户端自动路由到——除非你显式指定该节点地址并强制读取。它本质是“对客户端不可见 + 不参与投票”,不是“只读专用通道”。
常见错误现象:rs.conf() 里写了 "hidden": true,但应用用 readPreference=secondary 还是查不到这台机器;或者误以为它能分担主库读压力,结果流量压根没过去。
-
hidden: true必须配合priority: 0使用,否则 MongoDB 会拒绝保存配置(报错Cannot set hidden to true on a member with priority > 0) - 该节点仍会同步数据,但
rs.printSecondaryReplicationInfo()不会把它算进延迟统计里 - 连接时必须用完整 host:port 直连,不能依赖 replica set discovery;驱动默认忽略 hidden 节点
离线统计查询前必须关掉 slaveOk 或改读偏好?
不用关 slaveOk,但得绕过 driver 的自动节点筛选逻辑。MongoDB 驱动(比如 Node.js 的 mongodb 包)在构建连接串时,默认过滤掉 hidden: true 和 arbiterOnly: true 节点,哪怕你写了地址进去。
使用场景:你有一台专用于跑 db.collection.aggregate(...) 或导出全量日志的从节点,不想干扰线上读写,也不希望它被意外选为 primary。
- Java 驱动需用
ComposableServerSelector手动指定 host;Python 的pymongo得用directConnection=True+ 单节点 URI,例如mongodb://host:27018/?directConnection=true - Node.js 下避免用
replicaSet参数,改用单点连接:new MongoClient('mongodb://host:27018') - 切记不要在 hidden 节点上执行写操作或
rs.reconfig(),它没有选举权,reconfig 会失败并可能触发全集群重加载配置
rs.reconfig() 修改 hidden 属性时为什么总卡住或报错?
因为 hidden 节点在 reconfig 过程中会被临时剔除出 replica set 视图,如果操作不当,整个 set 可能无法达成多数派,导致 reconfig 超时或阻塞。
参数差异:直接改 members[n].hidden 是危险操作;正确做法是先调低 priority,等它自然退为 secondary,再加 hidden 标记。
- 必须用
force: true参数才能对 hidden 节点做 reconfig(否则报not master and slaveOk=false) - 推荐步骤:先
rs.reconfig({...}, {force: true})把目标节点priority: 0;等它状态变成SECONDARY(rs.status().members[n].stateStr);再发一次 reconfig 加hidden: true - 别在 primary 上执行完 reconfig 就立刻断开——要等
rs.conf()返回新配置且rs.status()显示所有成员状态稳定,否则可能回滚配置
hidden 节点跑聚合查询慢,是不是该调大 maxTimeMS?
慢往往不是因为超时限制,而是它本身没索引、磁盘 I/O 差、或被主节点同步流抢占资源。调 maxTimeMS 只是掩盖问题。
性能影响:hidden 节点照样走 oplog 同步,如果主库写入猛,它的 apply 线程和你的统计查询会争抢 CPU 和磁盘带宽;而且默认不开启 readConcern: "majority",可能读到中间态数据。
- 聚合前先确认它是否已追平:
rs.status().members[n].optimeDate和 primary 的差值应 - 建专用索引:hidden 节点可以加索引,不影响主库,但注意索引构建过程会锁表(WiredTiger 下是 per-collection lock)
- 如果只是导出,用
mongodump --host host:27018 --oplog比连 shell 跑 aggregate 更稳,避免长连接拖垮节点
最容易被忽略的一点:hidden 节点的 local 库里没有 system.replset 的最新快照,所以 rs.conf() 在它上面查出来的是旧配置——别信它返回的 hidden 字段值,一切以 primary 上的 rs.conf() 为准。










