wiredtiger缓存重启后全空导致initial sync卡住,因需从磁盘重读全部数据页,io压力大、page fault频繁;可通过顺序扫描或mongodump预热加速cache加载,或满足条件启用fast sync跳过全量同步。

WiredTiger缓存重启后全空,为什么同步卡在 initial sync 阶段?
MongoDB副本集节点重启后同步慢,核心原因不是网络或 oplog 延迟,而是 WiredTiger 的 cache(默认 50% 物理内存)被清空,所有数据页要从磁盘重新读取——尤其是 initial sync 阶段需要扫描整个数据文件,IO 压力大、page fault 频繁,表现就是 top 看到 mongod 进程 CPU 很低但磁盘 iowait 持续 90%+。
- WiredTiger 不会自动“记住”上次加载的热数据,重启即冷启动
- initial sync 期间不走 oplog 复制,而是直接
cloneCollectionAsCapped+ 全量 BSON 扫描,对 cache 命中率极度敏感 - 若数据集远大于 cache(比如 2TB 数据,cache 只有 16GB),实际有效吞吐可能低于 10MB/s
怎么让 WiredTiger cache 在重启后快速“热起来”?
没有 magic button,但可通过预热绕过被动 page fault。本质是主动触发数据页加载进 cache,让后续 initial sync 或复制能命中内存。
- 用
db.collection.find().hint({$natural: 1}).limit(1).toArray()不够——只加载索引页和少量数据页 - 真正有效的是顺序扫描:执行
db.runCommand({collStats: "your_collection", verbose: true})后观察size和count,再用db.your_collection.find().batchSize(10000).noCursorTimeout().allowDiskUse()遍历(注意加noCursorTimeout()防中断) - 更稳妥的做法是用
mongodump --query '{"_id": {"$gt": ObjectId('000000000000000000000000')}}' --out /dev/null模拟读取,它会强制走 WiredTiger 层,且 batch 大小可控 - 预热前确保
wiredTigerCacheSizeGB已设为合理值(至少 > 单个集合热数据大小的 1.2 倍),否则预热本身就会触发频繁 eviction
initial sync 能否跳过全量拷贝,直接复用本地数据文件?
可以,但前提是该节点停机前是正常 secondary,且数据文件未被删改——这时启用 --replSet 启动时加上 --wiredTigerCacheSizeGB 和 --dbpath 指向原路径,MongoDB 会自动进入 “fast sync” 流程(也叫 “resync from local data”),跳过 clone,只拉取缺失的 oplog。
- 必须满足:
storage.mmapv1.journal.enabled关闭(MMapv1 已弃用,仅作对照)、wiredTiger.engineConfig.cacheSizeGB配置与之前一致,且dbpath下_mdb_catalog.wt和集合文件时间戳新于 last applied oplog timestamp - 检查是否触发 fast sync:日志里出现
Starting replication from local data, skipping initial sync,而非Starting initial sync - 如果误删了
local.oplog.rs或修改过storage.dbPath,MongoDB 会降级为 full initial sync,预热也没法加速这个过程
还有哪些配置会让同步变慢却被忽略?
很多团队调了 cache 却忘了配套参数,结果预热白做。
-
storage.wiredTiger.engineConfig.journalCompressor设为none可减少 journal 写放大,尤其在 HDD 上明显——但别在生产环境关 journal -
replication.oplogSizeMB过小(如默认 512MB)会导致 primary 上旧 oplog 被覆盖,secondary 重启后发现 gap 太大,被迫 fallback 到 initial sync -
net.maxIncomingConnections默认 65536 足够,但如果用mongos中转或有大量客户端连接,可能占满 fd,导致 replica set 内部 heartbeat 超时,间接拖慢 sync 状态切换 - Linux 的
vm.swappiness=1是硬性要求,swappiness > 10 时 WiredTiger cache 容易被 swap 出去,一次 major fault 就卡住几秒
冷启动预热不是银弹——它解决的是 cache 缺失问题,但若磁盘本身是机械盘、或数据局部性差(比如按时间分片但查询随机)、或 oplog 窗口太短,这些才是根因。预热只是把“等 IO”变成“主动读”,真慢的时候,得先看 mongostat 的 faults 和 netIn 是否匹配预期。











