暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MongoDB-从0到1-实时复制机制解析

原创 赵师的工作日 2024-12-18
367

主页.png

作者:赵师的工作日(赵明中)
现役Oracle ACE、MySQL 8.0 ocp、TiDB PCTA\PCTP、Elasticsearch Certified Engineer
微信公众号:赵师的工作日
CSND:赵师的工作日
二维码.png

一、MongoDB复制概述

MongoDB的复制机制基于主从结构,提供了高可用性和数据冗余。MongoDB的复制系统由一个主节点(Primary)和多个从节点(Secondary)组成,主节点处理写操作,并将这些操作通过复制传送到从节点。从节点同步主节点的数据,确保它们的数据一致性。

复制集(Replica Set)

在MongoDB中,多个节点(通常是三节点或五节点)通过复制集组成一个集群。每个复制集包含以下几种角色:

  • Primary:主节点,处理所有的写操作。
  • Secondary:从节点,从主节点获取数据并同步更新。它们可以充当备份节点,提供容灾能力。
  • Arbiter:仲裁节点,它不会存储数据,只参与选举操作。通常用于提供奇数节点以避免在选举时发生投票平局的情况。

MongoDB复制集提供了以下特点:

  • 数据冗余
  • 高可用性
  • 数据自动恢复

二、实时复制的工作原理

在MongoDB的复制机制中,主节点和从节点之间的同步是实时的。实时复制的关键是通过oplog(操作日志)来实现的。
Oplog(操作日志)
Oplog是MongoDB复制的核心,它是一个特殊的集合(local.oplog.rs),用于记录所有的写操作。这些写操作包含增、删、改等操作。主节点会将所有操作记录到Oplog中,从节点会不断地读取这个日志并同步数据。

Oplog的工作流程:

(1)主节点接收到写操作请求并执行操作。
(2)主节点将写操作记录到Oplog中。
(3)从节点会周期性地从主节点的Oplog中拉取最新的操作,并在本地执行相同的写操作,以保持数据同步。

实时复制的同步流程:

(1)写操作到达主节点: 写操作首先到达主节点,主节点执行该操作后,将其记录到oplog中。
(2)从节点拉取Oplog: 从节点不断监视主节点的Oplog,并从中拉取新的写操作(如插入、更新、删除等)。
(3)同步数据: 从节点根据Oplog中的操作记录,按照相同顺序执行操作,以保持数据与主节点一致。
(4)延迟处理: 主节点和从节点之间的数据同步通常是实时的,但由于网络延迟、磁盘写入等因素,可能会出现微小的延迟。

三、数据同步的机制:拉模式 vs 推模式

MongoDB的复制采用拉模式来同步数据,而不是推模式。
拉模式

  • 从节点主动连接主节点拉取Oplog中的操作记录。
  • 从节点按顺序执行这些操作,保证与主节点数据一致。
    这种拉模式的优点是从节点可以根据自己的进度来拉取数据,不必等待主节点主动推送,从而减少了网络负担。

四、数据一致性与复制延迟

尽管MongoDB提供了实时复制机制,但由于复制是异步的,因此可能存在一定的延迟。即从节点可能会落后于主节点,无法立即看到主节点上的所有数据更改。
一致性模型
MongoDB提供了多种一致性级别,用户可以根据需要选择适当的一致性保证:

  • 节点级别的写入一致性(Write Concern):指定写操作需要多少节点确认才能认为写操作成功。
  • 读取一致性(Read Concern):指定读取操作从哪些节点读取数据,并保证读取数据的一致性。
    在MongoDB 4.4开始,提供了更多的选项来平衡性能和一致性需求。通过majority写入关心和linearizable读取关心,用户可以确保在分布式环境下的数据一致性。

五、实时复制中的故障恢复

在MongoDB复制集中,如果主节点发生故障,MongoDB会启动一个自动选举机制,通过仲裁节点或者从节点的投票选举出一个新的主节点。这一过程是自动的,确保复制集能够继续提供服务。

(1)主节点故障: 如果主节点故障,复制集中的从节点将进入选举状态,并通过多数节点选举出新的主节点。
(2)自动恢复: 新的主节点会接管写操作,并通过Oplog继续同步数据。故障发生时,MongoDB尽量确保最小的停机时间。

六、代码层面:实时复制的实现

在MongoDB的源代码中,实时复制的实现主要集中在以下几个模块:

  • Replication:负责协调复制集中的各个节点,处理Oplog日志、复制流、故障转移等功能。
  • Oplog:MongoDB的每个写操作都在oplog中记录,Oplog的操作日志是复制的核心。
  • Sync:负责从节点拉取Oplog并同步数据。
    具体到MongoDB 4.x以上源码中,Oplog的相关操作可以在replication模块中找到。Oplog的相关实现涉及到OplogWriter(写操作)和OplogReader(读操作)等组件。
    类源代码实现:
  • Oplog日志的写入:
cpp
Status ReplicationCoordinatorImpl::logOp(OperationContext* opCtx,
                                         const BSONObj& op) {
    auto oplogEntry = createOplogEntry(op);
    try {
        writeToOplog(opCtx, oplogEntry);
    } catch (const DBException& e) {
        return e.toStatus();
    }
    return Status::OK();
}
  • 从节点拉取Oplog:
cpp
void ReplicationExecutor::processOplogEntries() {
    while (true) {
        // 拉取新的Oplog数据
        auto oplog = oplogFetcher.fetchNextOplogEntry();
        if (oplog) {
            applyOplog(oplog);
        }
    }
}

这些代码片段展示了如何处理Oplog的写入和从节点如何拉取Oplog并同步数据。

七、性能优化与挑战

尽管MongoDB提供了实时复制的机制,但在大规模生产环境中,仍然需要关注一些性能优化点:

  • 网络带宽: 高写入压力下,复制过程可能导致网络带宽的消耗,需要保证足够的网络资源。
  • Oplog大小: 如果Oplog日志过大,可能会影响性能。因此,合理的Oplog大小和清理机制至关重要。
  • 复制延迟: 在高负载情况下,可能会出现一定的复制延迟。可以通过监控工具(如MongoDB Atlas或rs.printSlaveReplicationInfo())来实时查看延迟情况。
最后修改时间:2025-01-02 19:29:27
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论