记一次Mongo Secondary 同步中断
背景
想用mongo_exporter 来监控shard集群,但不想用现成的管理员账号,想单独创建一个monitor账号,想当然的以为在每个shard节点都创建一个monitor账号就行,于是在第一个Primary shard上创建账号的时候就卡着了,创建的命令如下:
db.createUser(
{
user: "monitor",
pwd: "qn12345h",
roles: [ { role: "__system", db: "admin" } ]
}
)
正当我百思不得其解为啥创建用户都会卡住的时候,收到了secondary shard 掉线的告警,赶紧查查 secondary shard 的日志,发现有 REPL(复制) 相关错误日志,刚好是在重放创建monitor 用户的这个操作失败,Failed to apply operation due to missiong collection (… ,联想到部署集群的时候,刚创建shard集群的时候是没有账号的,是后面改为单机模式再创建的账号,初步确定是不应该在已经运行的sharding 集群中再创建账号。
- 尝试寻找参数是否有类似 Mysql ‘sql_slave_skip_counter’ 之类的可以跳过几步的参数,未果
- 查阅官网和博客上有关 Mongo replica 同步逻辑的资料,发现是secondary 是通过拉取 primary shard 上的oplog(local库 下 oplog.rs 集合)并在自身重放来实现的同步。于是登录 primary 节点想删除对应的oplog记录,结果没法删除。提示 can not remove capped collection: local.oplog.ts , 得知oplog 是一个caped collection ,所有记录按时间先后顺序写入,无法被修改。
use local
db.oplog.rs.remove({"ts":Timestamp({.........})}) #根据报错的记录获得ts字段值
-
尝试重做secondary 节点,在中文社区 https://mongoing.com/docs/core/replica-set-sync.html 找到,可以重新开始一次初始同步,于是将secondary shard 的 data 节点mv 备份,重新创建新的data节点,再次启动secondary shard ,通过日志可以发现正在同步数据。
-
primary shard 上执行命令查看状态
>> rs.status()
members: [
......
"stateSrt": "STARTUP2" # 该状态表明配置加载完,正在初始化
]
- 复制完成后再查看状态
>> rs.status()
members: [
......
"stateSrt": "SECONDARY" #该状态表示已复制完成,当前节点是备份节点
]
总结
因为在primary shard上执行过 创建用户的命令,primary shard上的 oplog 一直记录着这条操作,secondary 节点使用oplog同步的时候,每同步到这个地方就会因为无法继续同步而中断。只有通过重新初始化同步,通过克隆的方式将源的所有记录同步到secondary 本地,先获得某一个时刻全量的数据后,再从这个时刻开始通过oplog 继续同步,有效避开了异常的oplog记录。