无休止的恢复状态

tot*_*i05 8 replication mongodb

我在MongoDB 3.0.2上构建了一个包含一个主服务器,一个辅助服务器和一个仲裁服务器的复制集.主服务器和仲裁服务器位于同一主机上,辅助服务器位于另一台主机上.

随着写入过载的增加,二级不能跟随主要步骤进入恢复状态.主服务器可以连接到辅助服务器,因为我可以通过主服务器上的Mongo shell登录到辅助服务器.

我停止所有操作并使用该命令观察辅助状态,rs.status()rs.syncFrom("primary's ip:port")在辅助节点上键入命令.

然后该rs.status()命令的结果显示辅助的optimeDate远远落后于主要的optimeDate,并且间歇性地出现一条消息,如下所示:

"set" : "shard01", "date" : ISODate("2015-05-15T02:10:55.382Z"), "myState" : 3, "members" : [ { "_id" : 0, "name" : "xxx.xxx.xxx.xxx:xxx", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 135364, "optime" : Timestamp(1431655856, 6), "optimeDate" : ISODate("2015-05-15T02:10:56Z"), "lastHeartbeat" : ISODate("2015-05-15T02:10:54.306Z"), "lastHeartbeatRecv" : ISODate("2015-05-15T02:10:53.634Z"), "pingMs" : 0, "electionTime" : Timestamp(1431520398, 2), "electionDate" : ISODate("2015-05-13T12:33:18Z"), "configVersion" : 3 }, { "_id" : 1, "name" : "xxx.xxx.xxx.xxx:xxx", "health" : 1, "state" : 7, "stateStr" : "ARBITER", "uptime" : 135364, "lastHeartbeat" : ISODate("2015-05-15T02:10:53.919Z"), "lastHeartbeatRecv" : ISODate("2015-05-15T02:10:54.076Z"), "pingMs" : 0, "configVersion" : 3 }, { "_id" : 2, "name" : "xxx.xxx.xxx.xxx:xxx", "health" : 1, "state" : 3, "stateStr" : "RECOVERING", "uptime" : 135510, "optime" : Timestamp(1431602631, 134), "optimeDate" : ISODate("2015-05-14T11:23:51Z"), "infoMessage" : "could not find member to sync from", "configVersion" : 3, "self" : true } ], "ok" : 1

"infoMessage":"无法找到要同步的成员"

主要和仲裁者都可以.我想知道此消息的原因以及如何将辅助状态从"恢复"更改为"辅助".

Mar*_*erg 10

问题(最有可能)

主要的最后一次操作来自"2015-05-15T02:10:56Z",而次要的最后一次操作来自"2015-05-14T11:23:51Z",这是大致的差异15个小时.该窗口可能会超出复制oplog窗口(oplog中第一个和最后一个操作条目的时间之间的差异).简而言之,对于辅助设备来说,主设备上的操作太多了.

更详细一点(尽管简化):在初始同步期间,辅助同步的数据是给定时间点的数据.当同步该时间点的数据时,辅助连接到oplog并应用在所述时间点之间和现在根据oplog条目进行的更改.只要oplog在所提到的时间点之间保存所有操作,这就可以正常工作.但是oplog的大小有限(它是一个所谓的上限集合).因此,如果在初始同步期间主要操作上发生的操作多于oplog可以保持的操作,则最旧的操作将"淡出".次要识别并非所有操作都可用于"构造"与主要数据相同的数据并且拒绝完成同步,保持RECOVERY模式.

解决方案

问题是已知问题而不是错误,而是MongoDB内部工作的结果以及开发团队做出的几个故障安全假设.因此,有几种方法可以处理这种情况.遗憾的是,由于您只有两个数据承载节点,所有都涉及停机时间.

选项1:增加oplog大小

这是我首选的方法,因为它只处理一次问题,并为所有人处理(种类).不过,它比其他解决方案要复杂一些.从高层次的角度来看,这些是您采取的步骤.

  1. 关闭主要
  2. 使用直接访问数据文件创建oplog的备份
  3. 重新启动mongod独立模式
  4. 将当前oplog复制到临时集合
  5. 删除当前的oplog
  6. 重新创建具有所需大小的oplog
  7. 将oplog条目从临时集合复制回闪亮的新oplog
  8. mongod作为副本集的一部分重新启动

在进行初始同步之前,不要忘记增加辅助的oplog,因为它可能在将来的某个时间成为主要的!

有关详细信息,请阅读有关副本集维护的教程中的"更改oplog的大小".

选项2:在同步期间关闭应用程序

如果选项1不可行,唯一真正的其他解决方案是关闭应用程序,从而导致副本集上的负载,重新启动同步并等待它太完整.根据要传输的数据量,计算几个小时.

个人笔记

oplog窗口问题是众所周知的.虽然使用MongoDB可以轻松设置副本集和分片集群,但是需要相当多的知识和一些经验来正确维护它们.在不知道基础知识的情况下,不要运行具有复杂设置的数据库这样重要的东西 - 如果发生错误(tm),可能会导致情况FUBAR.


Ste*_*rry 9

另一个选项(假设主数据包含健康数据)只是删除辅助mongo数据文件夹中的数据并重新启动.这将导致它同步回主服务器,就像您刚刚将其添加到副本集一样.