同步

每个备份节点都维护着自己的 oplog,记录着每一次从主节点复制数据的操作。由于 oplog 大小是固定的,它只能保持特定数量的操作日志。

初始化同步

副本集中的成员启动后,就会检查自身,确认是否可以从某个成员那里进行同步。如果不行,它就会尝试从副本的另一个成员那里进行完整的数据复制。这个过程就是初始化同步。

初始化同步有以下几个过程

  1. 将现有数据删除

  2. 克隆,就是将同步源的所有记录全部复制到本地。

  3. 进入到 polog 同步的第一步,克隆过程的所有操作都会被记录到 oplog 中。如果在这过程中有文档被移动,就可能被遗漏,导致没有被克隆,可能需要重新进行克隆。

  4. 接下来是 oplog 同步过程的第二步,用于将第一个 oplog 同步的操作记录下来。

  5. 开始创建索引。如果集合比较大,或者要创建的索引比较多,这个过程会比较耗时。

  6. 如果当前节点的数据任意远远落后于同步源,那么 oplog 同步过程的最后一步就是将创建索引期间的所有操作全部同步过来,防止改成员成为备份节点。

  7. 现在,当前成员完成了初始化同步,切换到同步状态,这时当前成员就可以成为备份节点了。

处理陈旧数据

如果备份节点远远落后于当前的操作,那么这个备份节点就是陈旧的。为了避免陈旧备份节点的出现,让主节点使用比较大的 oplog 保存足够的操作日志是很重要的。

心跳

为了维护集合的最新视图,每个成员每隔两秒钟就会向其他成员发送一个心跳请求。心跳请求的信息量非常少,用于检查每个成员的状态。心跳最重要的作用是让主节点知道自己是否满足集合“大多数”的条件。如果主节点不再得到“大多数”服务器的支持,它就会退位,变成备份节点。

成员状态

每个成员会将自己当前的状态告诉其他成员。

  • STARTUP

成员刚启动时处于这个状态。这个状态下,会尝试加载成员的副本集配置。配置加载完成后,就进入 STARTUP2 状态。

  • STARTUP2

整个初始化同步过程都处于这个状态,普通成员这个状态只会持续几秒。创建几个线程,用于复制和选举,然后切换到 RECOVERING 状态。

  • RECOVERING

这个状态表明成员正常运转,但是暂时不能处理读取请求。如果有成员处于这个状态,可能造成轻微的系统过载。

  • ARBITER

在正常的操作中,仲裁者应该始终处于 ARBITER 状态。

  • DOWN

一个正常运行的成员变得不可达,它旧处于 DOWN 状态。

  • UNKNOWN

如果一个成员无法到达其他任何成员,其他成员就无法知道它处于什么状态,就将其报告成 UNKNOWN 状态。

  • REMOVED

当处于被移出副本集时,它处于这种状态。如果它又被重新添加到副本集中,它就会回到“正常”状态。

  • ROLLBACK

如果成员正在进行数据回滚,它处于 ROLLBACK 状态。回滚结束时,服务器会转换为 RECOVERING 状态,然后成为备份节点。

  • FATAL

如果一个成员发生了不可挽回的错误,也不再尝试恢复正常的话,它就处于 FATAL 状态。

选举

当一个成员无法到达主节点时,它会申请被选举为主节点。希望被选举为主节点的成员,会向它能到达的所有成员发送通知。当这个节点不符合候选人的要求,其他成员会得知相关原因:这个成员的数据落后于副本集,或者是已经有一个运行中的主节点。在选举时,其他成员不会允许进行选举。

假如没有发对的理由则进行投票,如果得到“大多数”赞成票,它就选举成功,会切换到主节点状态。否则,它仍然处于备份节点状态。

回滚

新成为主节点的备份节点和原主节点之间缺失一些操作,这时需要进行回滚进行同步操作,如果回滚失败,必须重新同步。

参考

[1] MongoDB权威指南