MongoDB:当主节点失败时

是的

我想了解 MongoDB 提供什么保证(如果有的话),因为它与在 Primary 永久或暂时失败的场景中的数据持久性有关,或者当它在网络级别与副本集的其余部分分离时。

我理解 w:1 写关注会发生什么。我理解日记的作用。

我不明白 MongoDB 如何决定在选择新主数据库时保留哪些写入以及丢弃哪些写入。在 4 节点(+仲裁器)集群中,N1 为主节点,N2、N3、N4 为辅助节点,在这种情况下:

  1. {w:majority, j:true} 写入命中主节点。
  2. 次要轮询更改,主要等待多数人确认。
  3. N2 确认更改。
  4. N3 已收到更改并正在应用它。
  5. 主要下降。
  6. N3 无法向 Primary 确认它已应用更改。
  7. 选举是被迫的。

问题:

  • 选举完成后写入是否可用?
  • 哪个节点将成为新的主节点是否重要?
  • 如果第 4 步没有发生,结果是否不同?
  • 如果 Primary 已收到 N3 的确认,结果是否会有所不同?
  • 如果 Primary 已确认写入,并且 N2 复制了写入已被多数人确认的事实,结果是否不同?
  • 如果 N2 和 N3 都复制了写入被多数人确认的事实,结果是否不同?

首先介绍一下背景:

mongodb 副本集使用操作日志进行复制。主节点的每次写入都会附加到 oplog。

每个辅助节点查询其同步源以获取 oplog 条目,并批量检索和应用它们。

Oplog 条目是幂等的,必须按顺序应用。

在将条目写入 oplog 本身之前,它们首先被写入日志。

如果节点在应用批处理时崩溃,从日志中重放整个批处理是安全的,因为每个条目都是幂等的。

成员相互报告他们最近应用的 oplog 事件的标识符。

由于 oplog 事件必须按顺序应用,这意味着每个节点都在报告条目之前应用了所有条目,之后没有应用。

在 5 个节点的副本集中,大多数是 3 个节点。w:majority节点不会向客户端/应用程序确认写入已完成,直到大多数节点报告其 oplog 已到达或通过添加写入的点。

副本集中的每个节点都监视其他每个成员。

如果主要节点意识到它无法与大多数投票节点通信,它将降级到次要节点。

如果辅助节点在几秒钟内(默认为 10 秒)与主节点之间没有任何通信,它将要求进行选举。

发起选举的节点会向每个副本集成员征求投票。

每个成员通常都会投“是”,他们可能会投“否”的几个原因是:

  • 候选节点的最新 oplog 条目不等于或比其他节点更新
  • 该节点与优先级等于或大于候选节点的主节点有当前通信

如果候选节点收到足够多的“是”票以构成副本集中的大多数投票节点,则它将转换为主节点并接受写入。

每次选举都会增加term副本集值。如果主机从包含高术语的其他节点接收到的心跳或其他消息,则它立即缩至辅助。

在你的场景中:

{w:majority, j:true} 写入命中主节点。

主要将:

  • 将写入应用到数据集的本地副本
  • 将操作写入日志
  • 将操作写入oplog

假设主要的 oplog 现在包含:

|时间 | 操作| |-----|------------| | T1 | 创建收藏| | T2 | 创建索引 | | T3 | 插入文档 1| | T4 | 插入文档 2| | T5 | 更新文档 1| | T6 | 插入文档 3|

我将使用 T5 的更新作为w:majority写入。

次要轮询更改,主要等待多数人确认。

  • 辅助节点可能不会同时接收数据
  • 每个二级可能有不同的最后应用条目
  • 辅助节点对基于写关注的 oplog 事件没有不同的响应(我认为辅助节点甚至不知道写关注)

N1 是主要的,N5 是仲裁者。在 T5 写入之前,其余节点显示以下最近应用的 oplog 事件:

N2:T4
N3:T4
N4:T2

N2 确认更改。

最近应用的 oplog 事件现在是:

N2:T5
N3:T4
N4:T3

N3 已收到更改并正在应用它。

这意味着 N3 不会向任何其他节点报告新的上次应用 oplog 时间,并且主节点仍然不会向提交写入的应用进程确认成功或失败。

主要出现故障

在主要失败之前的那一刻,每个成员最后应用的 optime 是:

N1:T6
N2:T5
N3:T4
N4:T3
N5:不适用

N3 无法向 Primary 确认它已应用更改。

在这种情况下是合理的。

选举是被迫的。

在适当的超时后,一个或多个辅助节点将要求进行选举。

让我们假设 N3 实际上确实完成了应用 T5 的操作。

如果 N4 恰好是第一个超时的人,它将要求进行选举,并要求所有成员投票。投票结果如下:

N4:是(总是为自己投票)
N5:否 - 我可以看到一个节点的 oplog 事件比你的更新
N3:否 - 我有一个比你最近的 oplog 事件
N2:否 - 同上

此时N2或N3将参加下一次选举,选票如下:

候选人 N3:是 - 自己
N5:是 - 你有最近的事件
N4:是 - 你比我更新
N2:是 - 你至少和我一样更新

本次选举成功,节点过渡到primary。

如果 N3 应用了来自 T5 的事件,无论它是否已报告给主节点,都可能发生此事件序列。由于所有节点都监视所有其他节点,因此 N3 将向 N2、N4 和 N5 报告。

请注意,如果 #4 没有发生,N3 仍将处于 T4,并且不会被选中,因为 N2 发生了最近的事件。

在任何一种情况下,任何参与选举的次要应用的最新事件都将被保留。

当 N1 恢复并尝试重新加入副本集时,新主节点上的 oplog 很可能已超出 T6。由于当前主节点不知道 T6 的写操作,并且前主节点不能成为辅助节点,除非它可以重放当前主节点的 oplog 条目,节点比较它们的 oplog 历史,直到找到一个共同点。

在这种情况下,这将是 T5。

然后,前一个主服务器回滚 T6 处的操作所做的更改,并将回滚的数据写入本地磁盘文件,以便稍后在必要时恢复。它从新的主节点请求 T5 之后的 oplog 条目,并开始作为辅助节点进行复制。

在这种情况下,唯一丢失的写入是由主节点处理但未复制到任何其他节点的写入。

如果 Primary 已确认写入,并且 N2 复制了写入已被多数人确认的事实,结果是否不同?如果 N2 和 N3 都复制了写入被多数人确认的事实,结果是否不同?

这个事实实际上不需要复制。每个节点都在监视其他节点,因此每个辅助节点都将清楚地知道大多数副本集已经看到了哪些 oplog 条目,而不会被告知。

唯一的区别是,如果 N3 也向主节点报告它已复制操作,则主节点可以向应用程序报告多数写入成功。

替代方案

如果

  • #4 没有发生
  • 故障是网络分区而不是节点故障
  • N1和N2在隔板的一侧,N3、N4、N5在另一侧

在这种情况下,N1 会意识到它无法联系大多数副本集,并会下台。

如果 N1 或 N2 试图要求选举,他们将无法获得所需的 3 票

由于落后,N4仍然不会被选为N3

当 N3 要求选举时,N4 和 N5 都会投“是”,因此 N3 将成为主要的。

这意味着当网络分区被修复时,N1 和 N2 都会发现它们有当前主节点不知道的写入。

在这种情况下,T5 和 T6 写入都将回滚。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

MongoDB:初始化主节点时始终接收127.0.0.1

如何在主节点失败或实例关闭后恢复主节点?

MongoDB 4.2 中没有主节点

主节点更改时,应用程序无法连接mongodb

MongoDb区域副本集-每个区域中的主节点?

当子节点调用主节点的回调时,如何更新子节点?

使用 redis sentinel 时如何使用密码保护主节点和副本节点?

安全模式打开时,Ambari名称节点启动失败。

奇数个主节点

MongoDB主副本在辅助副本可以自我同步之前失败

mongodb 缝合函数在使用节点模式 @jimp 时出错

节点-插入MongoDB(字节数组)时引发异常

使用 kubespray 创建 Kubernetes 集群时,主节点中的 kubectl 运行问题

当存在指向相同节点的反向链接时,如何使用 Graphviz 使主箭头笔直?

Mesos群集在使用plicated_log时无法选择主节点

没有主节点的Kubernetes节点

多节点Kafka集群中的主节点

将“主节点”与特定子节点连接

如何匹配节点及其与主节点的关系?

区分VMWare中的主节点和从节点

直接从主节点访问链接列表节点

在Jenkins中,如何仅在分支失败时才发送电子邮件,即主分支?

任务':app:transformClassesWithMultidexlistForDebug'的执行失败。生成主dex列表时出错

在macOS中部分升级失败时,有什么方法可以挂载主磁盘?

迁移到Google SQL时,更改主服务器失败

具有主节点和主节点的Ketama

连接到MongoDB时身份验证始终失败

MongoDB在本地运行,但是在尝试远程访问时失败

在Windows中安装Mongodb时出现“连接失败”错误