1

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

我了解 w:1 写问题会发生什么。我理解日记的作用。

我不明白 MongoDB 如何决定在选择新主节点时保留哪些写入以及丢弃哪些写入。在 4 节点(+arbiter)集群中,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 都复制了写入被多数人确认的事实,结果是否不同?
4

1 回答 1

5

首先是一些背景:

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

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

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

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

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

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

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

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

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

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

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

要求选举的节点将向每个副本集成员征求投票。

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

  • 候选者最近的oplog条目不等于或比其他节点更近
  • 节点当前与优先级等于或高于候选节点的主节点进行通信

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

每次选举都会增加term副本集的值。If the primary receives a heartbeat or other message from one of the other nodes that contains a higher term than when it was elected, it immediately steps down to secondary.

在您的场景中:

{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:是 - 你至少和我一样更新

本次选举成功,节点转为主节点。

如果 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 would still not be elected due to being behind N3

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

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

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

于 2020-09-01T05:45:38.590 回答