MongoDB 副本集由一组 mongod 实例(进程)组成,包含一个 Primary 节点和多个 Secondary 节点, Mongodb Driver(客户端)的所有数据都写入 Primary,Secondary 从 Primary 同步写入的数据,以保持副本集内所有成员存储相同的数据集,提供数据的高可用。
那么为什么要设置副本集呢?
副本集包含多个数据节点和可选的一个仲裁节点。而在数据节点中:只有一个 主节点(Primary Node),其他节点为 从节点(Secondary Nodes)。
各个节点成员通过心跳机制进行通信,为主节点与节点的通信的时间超过配置的 electionTimeoutMillis 期间(默认 10 秒)时,符合条件的从节点要求选举将自己指定为新主节点,群集尝试完成新主节点的选举并恢复正常操作。
**主节点:**副本集只能有一个主节点能够确认写入操作来接收所有写操作,并记录其操作日志中的数据集的所有更改(记录在 oplog 中)。
**应用日志(oplog):**它保存了修改存储在数据库中的数据的所有操作的 滚动记录,MongoDB 在主节点服务器上应用数据库操作,然后在主节点服务器的应用日志上记录操作,然后从节点成员在异步过程中通过心跳机制从任何其他成员导入应用日志并应用这些操作,应用日志中的每个操作都是幂等的。所有副本集成员都在 local.oplog.rs
集合中包含 oplog 的副本,这允许它们维护数据库的当前状态。
从节点: 复制主节点的应用日志并将应用日志记录的操作应用于其数据集,如果主节点宕机了,将从符合条件的从节点选举选出新的主节点,。 而且你可以通过配置实现特定的功能,比如:
仲裁节点: 仲裁节点不维护数据集。 仲裁节点的目的是通过响应其他副本集节点的心跳和选举请求来维护副本集中的仲裁。 因为它们不存储数据集,所以仲裁节点可以是提供副本集仲裁功能的好方法,其资源成本比具有数据集的全功能副本集成员更便宜。 如果您的副本集具有偶数个成员,请添加仲裁节点以获得主要选举中的大多数投票。而且仲裁节点总是只有 1 次选举投票,因此允许副本集具有不均匀的投票成员数,而没有复制数据的额外成员的开销。
心跳机制(Hearbeat): 副本集成员间默认每两秒会发送一次心跳信息,如果十秒未收到某个节点的心跳,则认为该节点已宕机不可以访问;如果宕机的节点为 Primary,Secondary(前提是可被选为 Primary)会发起新的 Primary 选举。仲裁员与其他集合成员之间的唯一沟通是:选举期间的投票,心跳和配置数据,而且这些交换未加密。
数据同步: 为了维护共享数据集的最新副本,副本的从节点设置同步或复制来自其他节点的数据。 MongoDB 使用两种形式的数据同步:初始化同步新节点同步完整的数据集,以及整个集群节点同步后续数据更改。
其中,初始化同步(Initial Sync)过程:
标准副本集架构由三台服务器,其中包括三个数据节点(一个主节点、两个从节点)或两个数据节点(一个主节点、一个从节点)和一个仲裁节点两种情况。如下所示:
三个数据节点:
当主库宕机后,两个从库都会进行竞选,其中一个变为主库,当原主库恢复后,作为从库加入当前的副本集群即可。
两个数据节点以及一个仲裁节点:
当主节点不可用时,将会选择从节点成为主 Primary,主节点恢复后,将其作为从节点加入到现有的副本集群中即可。
优先级 0 型节点不可以成为成为主节点,也不能触发选举。将从节点配置为优先级为 0 以防止它成为主节点,这在多数据中心部署中特别有用,在许多情况下,您无需将备用数据库设置为优先级 0。但是,在具有不同硬件或地理分布的副本集中,优先级为 0 的备用数据库可确保仅某些成员成为主数据库,这样可以根据实际网络分区的网络质量等实际情况进行配置。
例如,一个数据中心承载主数据中心和辅助数据中心:
第二个数据中心节点优先级为 0 只能是从节点数据库,而数据中心(1)中的节点才能成为主节点数据库。(比如你跨机房 A 和 B 部署了一个副本集,并且想指定 Primary 必须在 A 机房,这时可以将 B 机房的副本集成员 Priority 设置为 0,这样 Primary 就一定会是 A 机房的成员)
隐藏型(Hidden)节点:
由于延迟型从节点是数据集的滚动备份或运行历史快照,因此它们可以帮助您从各种认为错误中恢复。例如,延迟节点可以从不成功的应用程序升级和操作员错误(包括丢弃的数据库和集合)中恢复。而且延迟型从节点一定是优先级为 0 的从节点,也是隐藏型从节点。不能是主节点,也不能给客户端查询。
在选择延迟量,请考虑延迟量:
副本集节点可以通过配置 votes 字段来决定该节点是否具有投票权:
另外在副本集最多可包含 50 个成员,但只有 7 个投票成员,因此非投票成员允许副本集具有 7 个以上的成员。并投票成员只有具备以下状态可以进行投票:
配置:
{"_id": <num>,"host": <hostname:port>,"arbiterOnly": false,"buildIndexes": true,"hidden": false,"priority": 0,"tags": {},"slaveDelay": NumberLong(0),"votes": 0}
如果副本集中的主节点出现故障,那么主节点无法继续处理客户发出的请求。在 MongoDB 副本集中只有主节点可以处理客户发出的 写 请求,一旦主节点发生故障,客户难道无法继续往副本集中写任何数据吗?这种情况显然是无法满足高可用性的要求的。
副本集当中的主节点并非一成不变,同时也非使用者指定的而一直不会变化的,副本集当中的主节点其实是由整个副本集通过选举算法推选出来的。那么当原本的主节点无法继续工作的时候,会通过一次新的选举来从副本集当中其他的节点重选出新的主节点,如此便能恢复副本集的正常运作,主节点也能继续处理客户的写操作。
下面通过示例图描述副本集选举的过程:
在讲解副本集选举过程前,需要提及的是:副本集当中每个节点都会有所谓的选举计数器,英文称为 term
。计数器在每次在节点参与新的选举时候,都会将自身的选举计数器自增一,默认为 N
,表示所有节点到目前为止都参与了 N
次选举。
假设主节点 A 出现故障(崩溃、下线),其余两个副节点均可发起副本集选举。由于主节点 A 本应不停地为其余副节点发送心跳请求,当主节点 A 出现故障,那么很可能本应该发送的心跳请求超时,使得其他副节点发现主节点不再发送心跳请求,很可能原有的主节点不再工作。在这种情况下,任意副节点都可以发起一场新的选举,当然在实际情况当中,我们可以为不同的节点设置不同的优先级别,当各个节点的优先级别不同时,MongoDB 的算法会尽最大的努力,让优先级别高的副节点成为最先发起选举的节点,也就是说优先级别高的副节点有更大的可能性成为新的主节点。
假设副节点 B 发起选举,那么就称副节点 B 为候选主节点,他发起这场选举的目的,是为了讯问其余副节点,看大家是否同意选举节点成为新的主节点。
首先候选主节点会给自身的选举计数器 +1
,因为他要发起的是一场新的选举,他会为自己投票,这是完全允许的
然后会为其他节点发送投票请求,也就是询问其他节点是否愿意为该候选主节点投票
候选节点会把自身计数器的值也发送给投票节点 C,投票节点 C 收到投票请求后,发现候选节点计数器的值比投票节点计数器的值更大,会先把自身的计数器的值更新,与发起投票的候选节点的值同步值的大小,再决定投票结果发回给候选节点
投票结果或是同意,或是反对。投票节点通常通过候选节点和投票节点的同步性作为比较, 也就是比较与原本主节点的数据相似程度。当候选节点比投票节点分别与原本主节点比较的数据同步更高,那么投票节点就会为候选节点投出同意票。反之,则会投出反对票。
候选节点会把投票请求发送给副本集中的所有节点,当然包括失联的主节点。原本的主节点可能存在不正常的状态,他未必能响应成功的结果,那么会视该节点投了反对票
当候选节点收集了副本集中其他节点的投票结果之后,如果超过半数的其他节点(包括该候选节点本身所投的票)给该候选节点投了赞成票,那么该候选节点会当选成新的主节点。这时候该副本集将会恢复正常的运作,可以继续处理客户发来的读写操作
触发选举的事件是有多种的:
当应用数据量大或并发量上来后,单机模式肯定无法抗住压力,这个时候就需要考虑使用集群进行部署。MongoDB 目前为止支持三种集群模式:主从集群、副本集集群和分片集群。
副本集最多可包含 50 个成员,但只有 7 个投票成员。如果副本集已有 7 个投票成员,则其他成员必须是非投票成员。
副本集应该确保具有奇数个投票成员,如果您拥有偶数个投票成员,请部署仲裁节点,以便该集合具有奇数个投票成员。仲裁节点不存储数据的副本并且需要更少的资源。因此,您可以在应用程序服务器或其他共享进程上运行仲裁程序。
容错能力
副本集的容错是当变为不可用的成员数,并且仍然在副本集中留下足够的节点成员来选择主节点成员。容错是副本集大小的影响, 见下表:
选举成员数量 | 选举所需多数票 | 容错 |
---|---|---|
3 | 2 | 1 |
4 | 3 | 1 |
5 | 3 | 2 |
6 | 4 | 2 |
因此可以得出,将成员添加为偶数个到副本集并不总是会增加容错能力。但是,在这些情况下,其中将其中一个节点设置成隐藏型和延迟型从节点可以为专用功能提供支持,例如备份或报告。
提高读负载能力
在具有非常高读取流量的部署中,您可以通过将读取分发给从节点来提高读取吞吐量。随着部署的增长,将节点添加或移动到备用数据中心以提高冗余和可用性。
副本集分布在两个或更多数据中心
副本集分布在两个或更多数据中心的优势:
在不同地域部署数据节点(具有备用的数据中心)
要在数据中心发生故障时,请在备用数据中心至少保留一个成员。 如果可能,使用奇数个数据中心,并选择一个成员分布,以最大限度地提高即使丢失数据中心的可能性,剩余的副本集成员可以形成可以形成“大多数”选取出主节点,并有提供数据的副本的能力。为确保主数据中心的节点在备用数据中心的成员之前被选为主要成员,请将备用数据中心中节点members[n].priority
设置为低于主数据中节点,如下所示:
根据部署结构部署副本集示例 三个节点成员的副本集,成员合理分布以及解析如下:
五副节点成员的副本集,成员合理分布以及解析如下:
高可用集群具有自主选举能力,影响选取的因子和条件有以下:
参考资料: