一、同步原理核心概念
MongoDB 复制功能的核心是 操作日志(oplog)。
- Oplog:存储在主节点(Primary)的
local.oplog.rs 集合中。这是一个固定集合(Capped Collection),采用先进先出的策略记录所有修改数据的操作(增、删、改)。其固定大小意味着当日志写满后,会覆盖最旧的操作。
- 幂等性:Oplog中的每个操作都是设计成幂等的。这意味着无论同一个操作被应用一次还是多次,最终的数据状态都是相同的。这一特性是从节点(Secondary)可以安全地重放oplog,以及在网络中断后恢复同步的关键保障。
- 拉取模型:与许多主从复制架构不同,MongoDB采用从节点主动拉取主节点oplog的模型,而非由主节点推送。这赋予了从节点更大的自主性,例如可以选择从哪个同步源拉取数据。
二、初始化同步详解
当一个新节点加入副本集,或某个节点因故障导致数据落后太多时,就会触发初始化同步过程。这个过程旨在将源节点的全量数据完整复制到本地。
从MongoDB 5.2版本开始,初始同步支持逻辑同步和基于文件拷贝两种方式。逻辑同步是默认且更常用的方式,其流程可分解为四个有序阶段:
阶段一:全量数据克隆
- 目标节点扫描源节点上除
local系统库外的所有数据库。
- 将所有集合的文档数据复制到本地。
阶段二:缓冲增量Oplog
- 在全量克隆进行的同时,目标节点会启动一个后台线程,持续拉取源节点上新产生的oplog。
- 这些拉取到的增量操作被暂存于目标节点
local数据库的一个临时集合中,避免因克隆耗时过长而丢失期间的数据变更。
阶段三:应用缓冲Oplog
- 全量数据克隆完成后,目标节点开始将第二阶段暂存的oplog应用到本地数据集。
- 此步骤使目标节点的数据状态快速追赶上源节点在克隆完成时刻的状态。
阶段四:状态切换
- 完成上述所有步骤后,节点将其状态从
STARTUP2 转变为 SECONDARY。
- 至此,初始化同步完成,节点进入稳态复制阶段,开始持续的增量数据同步。
容错机制
现代MongoDB版本为初始化同步提供了更强的健壮性:
- 可恢复的初始同步:如果同步过程因临时网络错误或集合被删除等原因中断,目标节点会在接下来的24小时内尝试从中断点恢复,而无需从头开始整个耗时的过程。
- 重试上限:节点最多会自动重新启动初始同步过程10次。若超过此限制仍失败,节点将停止尝试并报错。
三、稳态复制流程解析
节点完成初始化同步后,便进入持续不断的增量复制状态,即稳态复制。
其内部采用了典型的生产者-消费者多线程模型,以实现高吞吐和低延迟的数据同步,具体流程如下:
数据流向与线程角色
| 组件 |
角色 |
功能 |
| OplogFetcher 线程 |
生产者 |
持续从选定的同步源节点拉取oplog流,并将获取到的操作放入一个内存队列(OplogBuffer)中。 |
| ReplBatcher 线程 |
缓冲处理器 |
从OplogBuffer中取出oplog条目,并按特定策略(如时间窗口或大小)打包成批次(batch),然后将其放入一个任务队列(OpQueue)。OpQueue会按文档ID进行哈希分区。 |
| OplogApplier 线程池 |
消费者 |
包含多个Worker线程。它们从OpQueue中领取任务(即oplog批次),并并发地将这些操作回放到本地的WiredTiger存储引擎中。 |
关键特性
- 流式复制:同步源以流的形式持续向从节点发送oplog,极大降低了复制延迟。
- 多线程并发应用:通过按文档ID哈希分区,确保对同一文档的修改操作被顺序执行,而对不同文档的操作则可以并行回放,充分利用多核CPU资源。
- 无锁读取:从节点在应用oplog批次时,对用户读请求使用WiredTiger引擎的快照功能进行处理,这意味着读取操作无需等待复制批次完成,保障了从节点的读性能。
同步源选择策略
从节点并非只能从主节点同步数据,这取决于链式复制的配置:
- 启用链式复制(默认):从节点可以选择从其他数据较新的从节点同步。这可以有效减轻主节点的网络出口负载,特别适用于跨地域部署或网络带宽受限的场景。
- 禁用链式复制:所有从节点都必须直接从主节点同步数据。这确保了所有从节点的数据延迟最小(相对于主节点),适用于对数据新鲜度要求极高、网络条件优良的环境。
同步源的选择是一个两轮筛选过程:
- 第一轮(严格筛选):候选源必须在线、可见,其oplog落后主节点不超过30秒,并且与目标节点有相同的副本集配置(如是否构建索引、是否有投票权等)。
- 第二轮(宽松筛选):如果第一轮没有找到合适源,则放松条件,仅要求候选源在线、可见且其oplog比目标节点更新即可。
流量控制
从MongoDB 4.2版本引入的流量控制机制,旨在防止从节点因处理能力不足而严重落后。
- 当大多数从节点的复制延迟超过
flowControlTargetLagSeconds(默认为10秒)时,主节点会主动限制新的写入操作速率。
- 这为从节点追赶数据提供了喘息之机,从而维护整个集群的稳定性与数据一致性。
四、异常处理:回滚机制
在分布式系统中,网络分区和节点故障是常态。MongoDB通过回滚机制来处理主节点切换后可能产生的数据不一致问题。
当一个旧主节点宕机后重新加入集群,如果发现自己在故障前执行的某些写入操作未被同步到新的主节点(即未在集群中达成“大多数”共识),这些“孤立”的操作就必须被撤销,此过程即为回滚。
回滚流程
- 寻找公共祖先:回滚节点会在自己的oplog和新主节点的oplog中,寻找两者最近的公共操作点(Last Common Ancestor, LCA)。
- 生成逆操作:对于自己存在但新主节点不存在的每一个操作,回滚节点会自动生成对应的逆操作(例如,
insert 对应 delete,update 对应一个能还原旧值的 update)。
- 执行回滚:应用这些逆操作,将自己的数据状态回退到与LCA一致的点。
- 保存回滚数据:被回滚(即删除或修改)的数据文档会被写入数据库目录下的
rollback 文件夹中,以便管理员在必要时进行手动检查和恢复。
触发回滚的常见场景
- 从节点严重失速:某个从节点落后太多,导致其同步源上的oplog游标所指向的操作已被覆盖,无法继续同步。
- 网络分区:原主节点与其他节点发生网络分区,在分区期间它仍在处理写入。当网络恢复后,它发现这些写入未被新形成的主节点集群所接受。
五、考点与架构设计启示
理解MongoDB的同步原理,不仅是应对相关技术面试的关键,更是设计高可用、强一致分布式系统的重要基础。
核心知识点回顾
- Oplog特性:固定集合、幂等性、存储在local库,是增量同步的基石。
- 同步类型:明确区分初始化同步(全量+追赶)与稳态复制(持续增量)的不同场景与流程。
- 链式复制:理解其权衡——启用可降低主节点负载、优化网络拓扑,但可能增加数据传播延迟。
- 回滚机制:知晓其触发条件(写关注未使用
majority、网络分区)和处理流程,这是保障集群最终一致性的安全网。
- 多线程复制模型:了解OplogFetcher、ReplBatcher、OplogApplier的分工与并发原理,是分析同步性能的框架。
架构设计与故障排查要点
在解决实际生产环境中的复制问题时,可遵循以下思路:
- 同步延迟高:检查主从节点间的网络带宽与延迟;确认从节点的硬件(CPU/IO)性能是否不足;评估主节点oplog尺寸是否过小,导致从节点频繁需要全量同步。
- 初始化同步失败:确保目标节点有足够的磁盘空间,尤其是存放临时oplog的
local数据库;调大oplog窗口大小,为克隆数据提供更充裕的时间。
- 降低回滚风险:对于关键数据写入,使用写关注(Write Concern)为
{w: "majority"}。这能确保写入操作在返回成功前,已复制到大多数节点,从而在主节点故障切换时极大避免数据回滚。
对于更深入的配置细节、性能调优及最佳实践,建议查阅 MongoDB官方文档。
参考资料
[1] 软考高级系统架构师MongoDB同步原理, 微信公众号:mp.weixin.qq.com/s/_KhAiTXc-l8KqV2IBwzTnA
版权声明:本文由 云栈社区 整理发布,版权归原作者所有。
|