作者介绍:简历上没有一个精通的运维工程师,下面的思维导图也是预计更新的内容和当前进度(不定时更新)。
数据库是一个系统(应用)最重要的资产之一,所以我们的数据库将从以下几个数据库来进行介绍。
MySQL
PostgreSQL
MongoDB(本章节)
Redis
Etcd
前面我们介绍了MySQL和PostgreSQL的主从模式,虽然底层原理不同,但是逻辑都是一样的,如果需要高可用,必须借助外部软件来实现,而我们今天讲的副本集则是MongoDB原生自带的功能(分布式集群)。
首先需要明确一个重要概念:在现代 MongoDB 版本(3.2 以后)中,传统的“主从”(Master-Slave)复制模式已经被官方废弃,并由功能更强大、更自动化的“副本集”(Replica Set)所取代。
因此,我们今天谈论的“MongoDB 主从原理”,实际上指的就是 副本集 的工作原理。下面我将从核心概念、工作原理、数据同步和故障转移四个方面来阐述。
一、核心概念
一个 MongoDB 副本集由一组维护相同数据集的 mongod 进程(实例)组成,包含以下三种角色:
- 主节点(Primary):
- 整个副本集唯一接收所有写操作的节点。
- 同时也会处理读操作。默认情况下,应用程序的读写都指向主节点。
- 将其操作记录到
oplog(操作日志)中。
- 从节点(Secondaries):
- 复制主节点的
oplog 并将这些操作应用到自己的数据集上,从而保持数据同步。 - 可以处理读请求。通过配置读偏好(Read Preference),可以将读请求分流到从节点,以减轻主节点压力。
- 一个副本集可以有多个从节点,提供数据冗余和高可用性。
- 仲裁节点(Arbiter):
- 一个特殊的角色,它不存储数据,也不参与数据复制。
- 唯一的作用是在主节点选举中进行投票,以帮助副本集在出现故障时能快速达成“多数派”,从而选出新的主节点。
- 通常在资源有限、无法部署完整数据节点的场景下使用。
关键点:一个副本集有且只有一个主节点。这是通过“选举”机制来保证的。
二、工作原理:数据同步(复制)
数据同步的核心是 Oplog (Operations Log)。
- Oplog 是什么?
- 它是一个有上限的集合(Capped Collection),存在于每个存储数据的节点(主节点和从节点)的
local 数据库中。 - 它记录了所有对数据集进行更改的操作(如插入、更新、删除)。每个操作都是幂等的,这意味着无论执行多少次,结果都是一样的。
- 它就像是数据库的“重做日志”。
- 同步流程:
- 步骤1: 客户端应用程序向主节点发起一个写操作(例如,
db.users.insert({name: "Alice"}))。 - 步骤2: 主节点在本地执行该写操作,并将此操作记录到自己的 Oplog 中。
- 步骤3: 从节点通过一个异步过程,持续地从主节点的 Oplog 中拉取(tail)新的操作条目。
- 步骤4: 从节点在自己的数据集中按顺序重放(replay)这些操作。由于操作是幂等的,即使重复执行也不会导致数据不一致。
这个过程保证了从节点的数据最终会与主节点保持一致,虽然是异步的,但延迟通常非常低。
三、工作原理:故障转移与选举
这是实现高可用性的核心。
- 心跳与健康检测:
- 副本集成员之间每两秒钟互相发送一次心跳包(ping)。
- 通过心跳,每个节点都能了解其他节点的状态(在线、离线、角色等)。
- 何时触发选举?
- 当从节点在超过配置的超时时间(默认10秒)内无法与主节点通信时,它会认为主节点已失效。
- 这个从节点就会发起一次新的选举,提议自己成为新的主节点。
- 选举过程:
- “大多数”的定义是
N/2 + 1,其中 N 是有投票权的成员数量。 - 例如,一个有 3 个节点的副本集(1主2从),“大多数”就是 2 票。
- 发起选举的节点会向副本集中的所有其他有投票权的成员(包括其他从节点和仲裁节点)发送投票请求。
- 每个成员只能投一票。
- 要成功当选为主节点,候选人必须获得“大多数”的投票。
- 获得大多数投票的节点成为新的主节点。
- 为什么需要“大多数”?
- 这是为了防止“脑裂” 问题。
- 在网络分区的情况下,原来的主节点可能在一个 minority(少数派)分区中,它无法获得大多数节点的认可,因此会被降级为从节点。这样就保证了在整个集群中,最多只有一个主节点,避免了数据冲突。
- 选举成功后的行为:
- 新的主节点开始接收所有的写操作。
- 其他节点开始从新的主节点同步数据。
- 当旧的主节点恢复后,它会以从节点的身份重新加入副本集,并开始从新的主节点同步数据。
所以在使用副本集的时候,需要把多个节点都写在应用的配置文件里面。
四、与传统主从模式的关键区别
| | |
|---|
| 不支持。主节点宕机后,需要手动干预指定新的主节点。 | |
| | 至少需要三个节点(或两个数据节点+一个仲裁节点)来实现高可用。 |
| | 更强的一致性保证,支持写关注(Write Concern)和读偏好(Read Preference)的灵活配置。 |
| | |