我在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”:“无法找到要同步的成员”
主要和仲裁者都可以。我想知道此消息的原因以及如何将辅助状态从“恢复”更改为“辅助”。
答案 0 :(得分:9)
主要的最后一次操作来自“2015-05-15T02:10:56Z”,而次要的最后一次操作来自“2015-05-14T11:23:51Z”,这是一个大约15个小时的差异。该窗口可能会超出复制oplog窗口(oplog中第一个和最后一个操作条目的时间之间的差异)。简而言之,对于辅助设备而言,主设备上的操作太多了。
更详细一点(尽管简化):在初始同步期间,辅助同步的数据是给定时间点的数据。当同步该时间点的数据时,辅助连接到oplog并应用在所述时间点之间和现在根据oplog条目进行的更改。只要oplog在所提到的时间点之间保存所有操作,这就可以正常工作。但是oplog的大小有限(它是一个所谓的capped collection)。因此,如果在初始同步期间主要操作上发生的操作多于oplog可以保持的操作,则最旧的操作将“淡出”。二级认识到并非所有操作都可用于“构建”与主要数据相同的数据并且拒绝完成同步,并保持RECOVERY
模式。
问题是一个已知的问题,而不是一个错误,而是MongoDB内部工作的结果和开发团队做出的几个故障安全假设。因此,有几种方法可以处理这种情况。遗憾的是,由于您只有两个数据承载节点,所有都涉及停机时间。
这是我首选的方法,因为它只处理一次问题,并为所有人处理(种类)。不过,它比其他解决方案要复杂一些。从高层次的角度来看,这些是您采取的步骤。
mongod
mongod
作为副本集的一部分在进行初始同步之前,不要忘记增加辅助操作的oplog,因为它可能会在将来的某个时间成为主要内容!
有关详细信息,请阅读"Change the size of the oplog" in the tutorials regarding replica set maintenance。
如果选项1不可行,唯一真正的其他解决方案是关闭应用程序,从而导致副本集上的负载,重新启动同步并等待它太完整。根据要传输的数据量,计算几个小时。
oplog窗口问题是一个众所周知的问题。虽然使用MongoDB可以轻松设置副本集和分片集群,但是需要相当多的知识和一些经验来正确维护它们。在没有了解基础的情况下,不要运行具有复杂设置的数据库这样重要的东西 - 如果发生了错误(tm),可能会导致情况FUBAR。
答案 1 :(得分:9)
另一个选项(假设主数据包含健康数据)是简单地删除辅助mongo数据文件夹中的数据并重新启动。这将使其同步回主服务器,就像您刚刚将其添加到副本集一样。
答案 2 :(得分:0)
向副本集添加第四个新节点。同步后,请重置失效的辅助服务器。