一、背景¶
为了调大 oplog window 窗口时间,在调大 oplog 的值后,引发了从库宕机。
日志抓取:
2022-08-30T08:32:40.761+0800 I REPL member to sync from
2022-08-30T08:32:40.761+0800 E REPL catch up -- enter ng maintenance mode
2022-08-30T08:32:40.762+0800 I REPL [replicat on 2) could not find
[rsBackgroundSync) too stale to [rsBackgroundSync) Our newest OpTime : { ts :
mestamp 1503977172000127 , t: 1 }
2022-08-30T08:32:40.762+0800 I REPL [rsBackgroundSync) Earliest OpTime available
is { ts: Timestamp 150399845100011, t: - 1 }
2022-08-30T08:32:40.762+0800 I REPL [rsBackgrou dSync] See http :
//dochub.mongodb.org/core/resyncingaverystalereplicasetmember
2022-08-30T08:32:40.762+0800 I REPL [rsBackgroundSync] going into maintenance
mode th 1820 other mantenance mode tasks in progress
2022-08-30T08:33:19.769+0800 I REPL candidate: 192.168.1.250:28000
2022-08-30T08:33:19.769+0800 I REPL [rsBackgroundSync] sync source
[repl cation 2] We are too stale to use 192.168.1.250:28000 as async
source.Blacklisting thiss source because
our last fetched timestamp: 59a4ded4:lb is before their earliest
timestamp:59a524a9:2le for lmin until: 2022-08-30T08:34:19.769+0800
二、原因¶
在本案例中存在延迟从库的问题,延迟从库由于延迟,还没有应用到 oplog 就被 "drop"了,进而导致延迟从库处于 recovering 状态。
三、解决方案¶
(1) 先取消延迟配置,扩容延时从库的 oplog 大小,再扩容主库的 oplog //db.adminCommand({replSetResizeOplog:1,size:1000})
(2) 对于主库需要先降级再进行升级操作。
rs.stepDown()
3.1 修改 oplog 有四种方法¶
3.1.1 方法一¶
步骤如下:
(1) 停掉所有 secondary 节点
(2) 主节点删除 local 目录下文件,副本节点删除数据目录下所有文件
(3) 修改所有节点的配置文件,如:oplogSize=1000
(4) 重启所有节点,包括主节点和副本节点
(5) 重新配置 replca set,副本节点会重新同步数据(initial sync)
优点:操作简单。
缺点:需要停服务,若数据量大,数据同步代价高。
3.1.2 方法二¶
步骤如下:
(1) remove 其中一个 secondary 节点,并关闭 mongod 服务,删除数据目录下所有文件
(2) 修改此节点的参数文件,如:oplogSize=1000,并启动 mongod 服务
(3) 在 primary 节点执行 rs.add()将此节点加入到 replica set
(4) 循环 1-3 步骤,将所有副本节点全部改完
(5) primary 节点执行 rs.stepDown()将主节点降级为副本节点
(6) 从新的主节点 remove 掉此节点,并进行步骤 1-3。这样逐个修改每个节点,完成 oplog 修改。
优点:解决了方法一中的停机问题。
缺点:每个节点都要逐个重新同步,时间代价更高。
3.1.3 方法三¶
The oplog exists internally as a capped collection, so you cannot modify its size in the course of normal operations.
另:改变 oplog 大小,需要在每个节点上执行维护模式。(官方推荐)
(1) 关闭 mongod
关闭 mongod 实例,如果是 primary 节点,执行 rs.stepDown() 降级
PRIMARY> rs.stepDown()
(2) 修改配置文件
修改配置文件,修改端口,注释掉 replSet 和认证相关的设置
(3) 启动 mongod 实例,并备份 oplog
mongod -f /mongodb/conf/mongodb.conf
mongodump -d local -c oplog.rs --port 27018 -h 172.16.254.134 -o /mongodb/backup
(4) 重建 oplog
保存 oplog 最新时间点
> use local
switched to db local
> db.temp.save( db.oplog.rs.find( { }, { ts: 1, h: 1 } ).sort( {$natural : -1} ).limit(1).next() )
WriteResult({ "nInserted" : 1 })
> db.temp.find()
{ "_id" : ObjectId("608a914089abaa981f14e888"), "ts" : Timestamp(1619693066, 1), "h" : NumberLong(0) }
#删除旧的 oplog
db.oplog.rs.drop()
#重建新的 oplog,大小为 2GB
> db.runCommand( { create: "oplog.rs", capped: true, size: (2 * 1024 * 1024 * 1024) } )
(5) 插入前面保存的 oplog 时间点记录
> db.oplog.rs.save( db.temp.findOne() )
> db.oplog.rs.find()
(6) 关闭 mongod 实例
> use admin
switched to db admin
> db.shutdownServer()
(7) 最后恢复 mongodb.conf 到初始状态,启动
3.1.4 方法四¶
如果你的 MongoDB 版本为 4.0 以后的版本,可以直接使用 replSetResizeOplog 修改。
(1) 查看 oplog 大小
SECONDARY> db.getReplicationInfo()
(2) 修改 oplog 大小
SECONDARY> db.adminCommand({replSetResizeOplog:1,size:2000})
(3) 验证 oplog 大小
SECONDARY> db.getReplicationInfo()
(4) 整理碎片,回收空间(可选)
> use local
switched to db local
> db.runCommand({"compact" : "oplog.rs"})