MongoDB复制流程


  • 註冊用戶

    当从库加入到副本集的时候,会判断自己是需要Initial Syc(全量同步)还是增量同步。那是通过什么条件判断的呢?

    1、判断全量同步及增量同步

    • 如果local数据库中的oplog.rs 集合是空的,则做全量同步。
    • 如果minValid集合里面存储的是_initialSyncFlag,则做全量同步(用于init sync失败处理)
    • 如果initialSyncRequested是true,则做全量同步(用于resync命令,resync命令只用于master/slave架构,副本集无法使用)

    以上三个条件有一个条件满足就需要做全量同步。

    我们可以得出在从库最开始加入到副本集的时候,只能先进行Initial Sync,下面我们来看看Initial Sync的具体流程

    2、全量同步流程(INIT SYNC)

    2.1、 寻找同步源

    这里先说明一点,MongoDB默认是采取级联复制的架构,就是默认不一定选择主库作为自己的同步源,如果不想让其进行级联复制,可以通过chainingAllowed参数来进行控制。在级联复制的情况下,你也可以通过replSetSyncFrom命令来指定你想复制的同步源。所以这里说的同步源其实相对于从库来说就是它的主库。那么同步源的选取流程是怎样的呢?

    MongoDB从库会在副本集其他节点通过以下条件筛选符合自己的同步源。

    • 如果设置了chainingAllowed 为false,那么只能选取主库为同步源
    • 找到与自己ping时间最小的并且数据比自己新的节点 (在副本集初始化的时候,或者新节点加入副本集的时候,新节点对副本集的其他节点至少ping两次)
    • 该同步源与主库最新optime做对比,如果延迟主库超过30s,则不选择该同步源。
    • 在第一次的过滤中,首先会淘汰比自己数据还旧的节点。如果第一次没有,那么第二次需要算上这些节点,防止最后没有节点可以做为同步源了。
    • 最后确认该节点是否被禁止参与选举,如果是则跳过该节点。

    通过上述筛选最后过滤出来的节点作为新的同步源。

    其实MongoDB同步源在除了在Initial Sync和增量复制 的时候选定之后呢,并不是一直是稳定的,它可能在以下情况下进行变更同步源:

    • ping不通自己的同步源
    • 自己的同步源角色发生变化
    • 自己的同步源与副本集任意一个节点延迟超过30s

    2.2、 删除MongoDB中除local以外的所有数据库

    2.3、 拉取主库存量数据

    这里就到了Initial Sync的核心逻辑了,我下面以图和步骤的方式给大家展现MongoDB在做Initial Sync的具体流程。

    本帖下載内容已隐藏,请登入以查看隐藏内容!

    注:这里不一定是Primary,刚刚提到了同步源也可能是Secondary,这里采用Primary主要方便大家理解。

    我们可以看到上述有6个步骤,那每个步骤具体做的事情如下:

    1)、 Sencondary 初始化同步完成之后,开始增量复制,通过produce线程在Primary oplog.rs集合上建立cursor,并且实时请求获取数据。

    2)、 Primary 返回oplog 数据给Secondary。 

    3)、 Sencondary 读取到Primary 发送过来的oplog,将其写入到队列中。 

    4)、 Sencondary 的同步线程会通过tryPopAndWaitForMore方法一直消费队列,当每次达到一定的条件之后,条件如下:

    • 总数据大于100MB
    • 已经取到部分数据但没到100MB,但是目前队列没数据了,这个时候会阻塞等待一秒,如果还没有数据则本次取数据完成。

    上述两个条件满足一个之后,就会将数据给prefetchOps方法处理,prefetchOps方法主要将数据以database级别切分,便于后面多线程写入到数据库中。如果采用的WiredTiger引擎,那这里是以Docment ID 进行切分。

    5)、 最终将划分好的数据以多线程的方式批量写入到数据库中(在从库批量写入数据的时候MongoDB会阻塞所有的读)。

    6)、 然后再将Queue中的Oplog数据写入到Sencondary中的oplog.rs集合中。


登录后回复
 

与 萌阔论坛 的连接断开,我们正在尝试重连,请耐心等待