bigywater.tech
MongoDB · 72

oplog 窗口:大小决定了落后多久还能追上

oplog 要设多大?secondary 离线多久还能追上?这篇量出各种写入产生的 oplog 字节数,算出不同 oplog 大小的窗口,并实测一次短暂离线后的追赶。

163 对 10,097 字节
小更新与 10 KB 文档插入平均每条 oplog 的大小
990 MB
replSetResizeOplog 允许的最小值
2.8 s
secondary 离线 15 秒后重启到追平所用的时间

窗口怎么看

实测 · 本机执行输出
  test> var r = db.getReplicationInfo(); ({logSizeMB: r.logSizeMB, usedMB: r.usedMB, timeDiff: r.timeDiff, timeDiffHours: r.timeDiffHours, tFirst: r.tFirst, tLast: r.tLast})
  {
    logSizeMB: 128,
    usedMB: 2.14,
    timeDiff: 11,
    timeDiffHours: 0,
    tFirst: 'Mon Oct 12 2026 12:28:36 GMT+0800 (China Standard Time)',
    tLast: 'Mon Oct 12 2026 12:28:47 GMT+0800 (China Standard Time)'
  }

窗口就是 oplog 里最早与最晚条目的时间差,db.getReplicationInfo() 的 timeDiff;oplog 写满后才反映稳态窗口。

写入类型

实测 · 本机执行输出
  update_one $inc 一个字段              oplog 新增  200 条,共    32,600 字节,平均每条      163 字节
  replace_one 整个文档(1 KB)            oplog 新增  200 条,共   230,600 字节,平均每条     1153 字节
  insert_one 1 KB 文档                oplog 新增  201 条,共   229,549 字节,平均每条     1142 字节
  insert_one 10 KB 文档               oplog 新增  201 条,共 2,029,549 字节,平均每条    10097 字节
  delete_one                        oplog 新增  200 条,共    24,000 字节,平均每条      120 字节

小更新($inc)每条约 163 字节,delete 约 120 字节,1 KB 文档的插入或整个替换约 1.1 KB,10 KB 的插入约 10 KB。写入的类型比条数更决定 oplog 增长速度。

窗口估算

实测 · 本机执行输出
  小更新($inc)     平均    163 字节 / 条 × 1000 条 / 秒 =    0.2 MB / 秒:128 MB 的 oplog 撑     823 秒,1 GB 撑    6587 秒,10 GB 撑   18.3 小时
  1 KB 文档插入     平均   1142 字节 / 条 × 1000 条 / 秒 =    1.1 MB / 秒:128 MB 的 oplog 撑     118 秒,1 GB 撑     940 秒,10 GB 撑    2.6 小时
  10 KB 文档插入    平均  10097 字节 / 条 × 1000 条 / 秒 =    9.6 MB / 秒:128 MB 的 oplog 撑      13 秒,1 GB 撑     106 秒,10 GB 撑    0.3 小时

窗口 = oplog 大小 ÷ 每秒产生的字节数:同样 1,000 次/秒,小更新下 128 MB 够 14 分钟,10 KB 插入下只够 13 秒。

逻辑大小与磁盘

实测 · 本机执行输出
  collStats: size = 4.8 MB,storageSize = 0.2 MB,maxSize = 128 MB,count = 1,030

collStats 的 size 是逻辑大小,storageSize 是压缩后的磁盘大小。

调整

实测 · 本机执行输出
  replSetResizeOplog size=100 MB → 失败 OperationFailure: BSON field 'size' value must be >= 990, actual value '100', full error: {'ok': 0.0, 'errmsg': "BSON 
  replSetResizeOplog size=990 MB → ok=1.0;maxSize 现在 990 MB

replSetResizeOplog 在线调整,最小 990 MB。

追赶

实测 · 本机执行输出
  secondary 离线 15 秒:primary 写入 1,411 条,oplog 新增 1,412 条 / 1.8 MB
  重启后 2.8 s 回到 SECONDARY 并追平;追到之后它的 live 集合 1,411 条(primary 上 1,411 条)

secondary 离线期间产生了 1.8 MB 的 oplog,重启后 2.8 秒追平;离线时间超过窗口就追不上,要重新 initial sync。

分步演示

oplog 窗口
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / MongoDB 9.0.2(Homebrew 的 mongod、mongos)/ mongosh 2.12.0 / pymongo 4.18.3;每个实验在临时目录里起全新的 mongod(独立 dbpath,端口 9900 以上,只监听 127.0.0.1,WiredTiger 缓存 0.25 GB),需要副本集或分片集群时在本机起多个进程;命令输出来自真实的 mongosh,批量写入、计时与多线程用 pymongo;计时用 time.perf_counter,数字每次运行会有小幅抖动,ObjectId、时间戳等每次运行都不同。3 个 mongod 副本集(oplog 128 MB);第三节是用第二节的实测字节数做的算术,不是实测的窗口
    • 没有验证:oplog 写满回绕后的稳态窗口,以及 secondary 落后超过窗口后“too stale”的表现——我试图把 128 MB 的 oplog 写到 650 MB(3 节点)和 976 MB(单节点),最早的条目始终没有被截断(serverStatus.oplogTruncation.truncateCount 一直是 0,原因没有查明),所以这一点没有演示;oplogMinRetentionHours;大事务对 oplog 的影响;flow control
    京ICP备2026067502号-1京公网安备11010502063487号