mongodb副本集oplogSize设置过小的问题
mongodb副本集构建的高可用方案,最少需要三个节点,一个主节点master,一个从节点slave,一个选举仲裁节点arbiter。当主节点奔溃的时候,仲裁节点选举从节点来接替主节点,继续提供数据服务,保证高可用。副本集方案中,从节点也会保存数据,他的数据是从主节点同步过来的,和mysql bin-log主从复制的方式类似,mongodb采用的是根据oplog来从主节点同步数据。oplog不是无限大,默认如果不手动设置,那么oplogSize就是磁盘空间的5%。超过了5%,oplog会被覆盖。
存在这么一种情况,slave因为某种原因挂掉了。正常情况下,他不会影响系统的正常运行,因为主节点正常运行,但是如果我们重新启动从节点,那么从节点会从主节点上恢复数据,这期间,如果主节点写入数据过快,oplog被覆盖了,也就是说,从节点需要恢复的数据不是从奔溃那一刻开始恢复的,这中间的数据被丢掉了,这种情况下,从节点不会正常的恢复,状态会变为RECOVERING,这就是本文需要讨论的一个问题。
oplog被覆盖,主要的原因是主节点写入数据过快导致的,写满了嘛。因为oplogSize有限定值,超过了这个限定值,那么就会被覆盖。这里来模拟oplogSize设置过小,从节点奔溃,然后恢复,出现RECOVERING状态的情形。
1、构建副本集构建 ,各个节点的配置如下图所示,同一个linux主机,三个mongod进程,分别开启端口27017,27018,27019。
启动节点,然后随便通过mongo shell登入一个节点,此时,节点没有表现出副本集的任何信息,当我们通过rs.initiate(cfg)设置之后,主节点会慢慢的变为OTHER->SECONDARY->PRIMARY。 在主节点,我们插入三条记录。
-
rs0:PRIMARY> use test
-
switched to db test
-
rs0:PRIMARY> db.user.insert({id:1,name:"zhangsan"})
-
WriteResult({ "nInserted" : 1 })
-
rs0:PRIMARY> db.user.insert({id:2,name:"lisi"})
-
WriteResult({ "nInserted" : 1 })
-
rs0:PRIMARY> db.user.insert({id:3,name:"wangwu"})
-
WriteResult({ "nInserted" : 1 })
2、从节点读取数据
我们设置了27017为主节点,27018为从节点,27019为仲裁节点,此时登入27018端口的从节点,我们试图查询数据db.user.find(),出现从节点无法查询的错误,从节点默认是无法读取数据的,更不可能写入数据。我们通过rs.slaveOk()让从节点可以查询数据。这数据是从master节点复制同步过来的。
副本集中slave是无法写入数据的。
打印oplogSize ,在启动的时候,我们通过--oplogSize 100设置了oplogSize为100M,因此,这里打印的是我们启动mongodb时设置的值。这个值在mongodb进程不崩溃的情况下设置多少无所谓。
3、为了模拟从节点奔溃并恢复,这里我们需要将slave节点手动停止。
4、批量插入数据: 在从节点停止之后,主节点是可以继续正常工作的,不会受到影响,这里为了让oplog被覆盖,我们向数据库中插入1000000条记录。
5、数据插入成功之后,我们需要再次恢复slave节点,启动mongod进程。
如果不出意外,100M的oplog被我们覆盖了,这时候,虽然slave节点的mongod进程启动,而且也可以通过mongo shell访问,但是我们通过rs.status()查看副本集状态,会出现如下所示的无法同步数据的情况。
6、oplog会被覆盖:
我们查看slave节点的日志,发现从节点恢复数据失败:
数据无法恢复,这时候,即使我们手动更改了oplogSize,生效了,oplog也无法恢复,因为已经被覆盖了。这时候需要将slave恢复到奔溃之前,也不是没有办法,就是删除slave节点所有的数据,从master节点完全同步复制。这是恢复slave从节点数据的方法之一。当然也是最直接的方式。
7、单纯对这个问题的解决办法: 删除slave节点存储的数据,重新启动slave从节点mongodb进程。针对本例的数据量不是特别大,会很快恢复。 我们查看slave节点日志,会发现状态从RECOERING恢复到了SECONDARY。
8、验证恢复是否成功:模拟slave节点奔溃之后,我们通过mongo shell向test数据库user表中插入了1000000条记录,加上奔溃之前的3条总共1000003条,说明从节点恢复数据成功,而且从mongo shell前面的"SECONDARY"标记可以看出,确实已经恢复了。
本例中,说明oplogSize设置过小100M,主节点写入数据过快而导致oplog被覆盖,确实会导致从节点恢复失败。
come from :https://blog.csdn.net/feinifi/article/details/88576140
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?