能分,但需显式配置readpreference为secondary或secondarypreferred,否则读请求默认全走主节点;事务、readconcern: 'majority'未满足或从节点延迟高时会自动降级回主。

主节点 CPU/IO 高,读请求真不能分到从节点?
能分,但默认不生效。MongoDB 的 readPreference 必须显式设置为 secondary 或 secondaryPreferred,驱动层才发读请求到从节点;否则所有读(包括 find、count、aggregate)都打在主节点。
- Node.js 驱动里要传
{ readPreference: 'secondaryPreferred' }到collection.find()或客户端选项里,不是只配连接字符串就完事 - Java 驱动需用
ReadPreference.secondaryPreferred()显式构造,Spring Data MongoDB 默认仍是primary - 注意:带写操作的事务、
readConcern: 'majority'且从节点未同步完时,secondary读会失败或自动降级回主节点 - 从节点延迟高(
optimeDate落后 >1s)时,secondaryPreferred可能仍走主——这不是 bug,是驱动的保底逻辑
Oplog 尾部扫描拖慢主节点?别盲目关 tailing
应用层用 changeStream 或自建 oplog watcher 时,如果每秒建立新游标、不复用 resumeToken,主节点就要反复扫描 oplog 尾部,触发大量磁盘随机读和锁竞争。
- Change stream 默认启用
tailing+awaitData,但若客户端频繁断连重连,每次都会触发一次全量 oplog 查找(尤其当startAfter丢失时) - 真实生产中,
oplog.rs大小建议 ≥ 24 小时写入量;小于 6 小时容易导致CursorNotFound或ChangeStreamHistoryLost - 不要为“省资源”把
oplogSize调到 512MB —— 单次写入峰值高时,几秒就能填满,引发频繁滚动和复制中断 - 监控关键指标:
repl.oplogTruncation.lagMillis(oplog 截断延迟),持续 >5000ms 说明 I/O 已成瓶颈
从节点扛不住读流量?先看它是不是真“空闲”
很多集群的从节点其实在默默干脏活:比如开启 slaveDelay 做延时备份、配置了 hidden: true 却被误加进读列表、或者运行着 mongodump 或 mongoexport 等离线任务。
- 执行
rs.printSecondaryReplicationInfo()查各节点 oplog 落后时间,落后 >30s 的从节点不适合接实时读 -
db.currentOp({ secs_running: { $gt: 10 } })看是否有长耗时查询卡在从节点上(比如没建索引的count({})) - 隐藏节点(
hidden: true)默认不参与读负载,但若应用代码硬编码了 host 列表并直连它,就等于绕过复制集路由逻辑 - 副本集内节点间网络延迟 >20ms 时,
readConcern: 'majority'会显著拉长读响应,此时应评估是否真需要该级别一致性
读分流后延迟突增?检查 writeConcern 和 journal 设置
把读切走后,主节点写压力没降反升,常见原因是调高了 writeConcern(如设成 { w: "majority" })但没同步调大 journal 刷盘间隔,导致日志写放大 + fsync 阻塞。
-
w: "majority"要求多数节点落盘,若从节点磁盘慢或网络抖动,主节点会卡在等待确认,表现为WriteConflict上升、networkIn持续高位 - 关闭
journal能减主节点 IO,但崩溃后可能丢最近 100ms 写入——别在生产环境关,除非你明确接受这个风险 - 更稳妥的做法:保持
journal: true,调大commitIntervalMs(默认 100ms)到 200–300ms,平衡持久性与吞吐 - 用
db.runCommand({ replSetGetStatus: 1 })中的optimes.lastCommittedOpTime对比各节点值,确认“多数派”是否真稳定
Oplog 抓取本身不消耗主节点 CPU,但它的磁盘顺序读会和 journal 刷盘争 I/O 队列;真正压垮主节点的,往往是没意识到读写分离后 writeConcern 和 journal 的隐性耦合。










