副本集本身不自动负载均衡,仅提供冗余与故障转移;读负载分担必须显式配置readPreference(如secondaryPreferred),否则默认readPreference=primary导致所有读请求仍集中于Primary节点。
副本集本身不自动做负载均衡,它只提供数据冗余和故障转移能力;真正的读负载分担,必须显式配置 readPreference 并配合合理的连接字符串与客户端驱动行为。否则所有读请求仍会打到主节点,副本集只是“摆设”。
因为 MongoDB 默认读写都走 primary —— 这是强一致性保障,但不是负载均衡策略。即使你部署了 3 个节点的副本集,只要没在连接时指定读偏好,驱动就不会把查询发给 Secondary。
readPreference=primary(默认):所有读强制走主节点,Secondary 完全闲置readPreference=secondaryPreferred:优先发 Secondary,主节点仅在无可用从节点时兜底readPreference=nearest:按网络延迟选最近节点(主或从都可能),适合多机房部署secondary 模式要求从节点已同步完成(optimeDate 接近主节点),否则驱动会跳过该节点不能只写 mongodb://node1:27017,node2:27017,node3:27017/db —— 这样驱动可能随机选一个节点连,且默认仍是 primary。必须显式带参数:
mongodb://node1:27017,node2:27017,node3:27017/db?replicaSet=rs0&readPreference=secondaryPreferred&maxStalenessSeconds=60
replicaSet=rs0 是关键,告诉驱动这是副本集拓扑,否则无法识别 Secondary 节点maxStalenessSeconds=60 表示允许最多落后主节点 60 秒的从节点参与读,避免因同步延迟导致读不到最新数据又不报错readPreference=secondary 生产环境,它会在所有 Secondary 不可用时直接报错,而不是降级到主节点不是所有读操作都适合走从节点。以下情况必须用 readPreference=primary 或手动覆盖:
session.startTransaction()):MongoDB 不支持跨节点事务,必须全程在 Primary 执行majority 写关注的场景:如果写入用了 w: "majority",但读用 secondary,仍可能读到旧值,因为 majority 提交 ≠ 立即同步到所有从节点.read('secondaryPreferred')
延迟不是靠猜的,得看 rs.status() 输出里的 optimeDate 和 lastHeartbeatRecv:
optimeDate 与 Primary 的差值,超过 5 秒就要警惕lastHeartbeatRecv 是否持续更新,若停滞说明网络或心跳失败oplogSize 小于 24 小时写入量)maxStalenessSeconds,但治标不治本;长期要扩容或优化从节点资源配置副本集的负载能力上限不在节点数量,而在从节点能否稳定跟上主节点的 oplog 重放速度。同步延迟一旦累积,readPreference 就会失效——驱动自动剔除“太老”的节点,最终所有读又回到 Primary。所以监控 optime 差值,比调参数更重要。