民哥MongoDB教程:MD副本集技术原理详解
在实际生产环境中,需要考虑数据冗余和高可靠性,即在不同的机器上存储副本,使数据不被损坏由一个点而丢失;能够随时应对数据丢失、机器损坏带来的风险。 MongoDB 副本集就是用来解决这个问题的。一组副本集是管理同一数据集的一组 mongod 实例。实例可以位于不同的机器上。一个实例包含一个从客户端接收所有写入操作的控件,其他实例是从主实例检索数据并保持同步的副本实例。
为什么要使用复印集?
生产部署时,保证数据冗余和可靠性,并在不同机器上保存副本,避免因单点损坏导致数据丢失。能够随时应对数据丢失和机器损坏带来的风险。换句话说,它还可以提高阅读能力。用户的读服务器和写服务器位于不同的位置,不同的服务器为不同的用户提供服务,增加了整个系统的负载。
在 MongoDB 中,这是副本集(副本集): 一组副本集是管理相同 mongod 实例的一组 mongod 实例。副本可以位于不同的机器。一个实例包含一个从客户端接收所有写入操作的控件,其他实例是从主实例检索数据并保持同步的副本实例。
副本集的成员有哪些?
上图中,我们了解了复制集的主节点(primary)和次节点(secondary)。此外,我们还需要了解更多的复制集成员,以彻底实现架构和相关配置。
主要成员
让我们看看主要成员:
- 主要
包含所有写入操作的日志。然而,副本服务器集群包含了主服务器的所有数据,因此如果主服务器挂掉了,副本服务器中就会选举出一台新的服务器来成为主服务器。
- 辅助节点(Seconary)
正常情况下,副本集的辅助节点参与主选举(也可以选为主),并同步主单元最后写入的数据,以保证与原始数据相同的存储空间。
中学可提供阅读服务。添加Secondary节点可以提供副本集读服务能力,提高副本集可用性。此外,Mongodb支持灵活配置副本集Secondary节点,以适应不同场景的需求。
- 仲裁节点(仲裁者)
仲裁节点仅参与投票,不能被选为主节点,不能同步主节点的数据。
例如部署2个节点的副本集,1主1备,该副本集无法提供服务(无法选择主节点)。目前,您可以将副本集添加到副本集中。即使节点已关闭,中间节点仍然可以选择主节点。
Arbiter本身不存储数据,是一个非常轻的服务。如果副本集成员数量为偶数,最好添加Arbiter节点以提高副本集可用性。
细化主节点(primary)
根据实现特定功能的需要,MongoDB还细化了主节点(Primary):
- 作为美丽的辅助,A备份副本。某些副本集可能无法在合理的时间内添加新成员。备用成员可以保持数据最新并可以替换不可用的成员。
Priority0 节点选择优先级为 0,不会被选为 Primary,说明 Primary 肯定是计算机空间 A 的成员。
(注意:这种方式部署时,最好将“大多数”节点部署在A机房,否则网络分裂时可能无法选择Primary)
- 隐藏
客户端不会分发读即使我们指定副本集读取选择,也会向隐藏节点发出请求。
这些隐藏节点不接受来自应用程序的请求。我们可以将隐藏节点专用于报告节点或备份节点。延迟节点也应该是隐藏节点。
隐藏节点无法被选为主节点(优先级为0),并且对驱动程序不可见。由于隐藏节点不接受驱动程序请求,因此您可以使用隐藏节点进行数据备份和离线计算,而不会影响副本集服务。
- Whistle
延迟节点数据集是延迟的,因此它可以帮助我们在人为错误或其他意外情况下恢复数据。
比如应用更新失败或者表、数据库被误删,我们可以通过延迟节点进行数据恢复。
延迟节点必须是隐藏节点,并且其数据落后于主节点一定时间(可配置,例如1小时)。
由于Delayed节点的数据滞后于Primary一定时间,如果Primary写入了错误或无效的数据,可以使用Delayed节点的数据恢复之前的时间点。
副本集最常见的部署架构是什么? ?它由两个子节点组成。如果主节点宕机,两个子节点都可以选举为主节点。
如果主节点消失,则会申请两个下属节点,其中一个成为主节点。当原主节点恢复后,可以作为子节点加入当前复制集群。
- 一个主节点
- 子节点可以选举成为主节点
- 仲裁节点只能参加选举投票,不能成为主节点
如果主节点宕机,子节点将被选举为主节点。主节点修复后,可以将其添加到现有的复制集群中。
跨数据中心
单个数据中心内的复制集容易受到断电、洪水、网络中断等数据中心故障的影响;因此,多个数据中心都是这样部署的。
为了在数据中心发生故障时保护数据,请在备份数据中心中维护至少一个成员。如果可能的话,使用奇数个数据中心,并选择成员的分布,最大限度地保证即使一个数据中心宕机,副本集的剩余成员也能形成多数或最少数量的副本来获取数据。三结。副本集的成员是一个仲裁器,该仲裁器与一个数据承载成员一起分布到数据中心1。
- 如果数据中心1发生故障,副本集将变为只读。
- 如果数据中心 2 发生故障,副本集仍可写,因为数据中心 1 的成员可以进行选举。
- 如果任意一个数据中心发生故障,副本集仍保持可写状态,因为其余成员可以容纳选举。
注意
将复制集成员分布在两个数据中心之间比单个数据中心具有优势。在双数据中心分布中,
- 如果其中一个数据中心发生故障,数据仍然可供读取,这与单数据中心分布不同。
- 如果成员数量较少的数据中心出现故障,副本集仍然可以进行并发的读写操作。
- 但是,如果成员最多的数据中心发生故障,副本集将变为只读。
如果可能,将成员分布在至少三个数据中心。对于配置服务器复制集 (CSRS),最佳实践是将其拆分到三个(或更多,具体取决于成员数量)中心。如果第三个数据中心的成本过高,一种分配选项是在两个数据中心之间平均分配数据承载成员,并将剩余成员存储在云中(如果公司政策允许平均)。
对于五节点
五成员副本集,一些可能的成员分布包括(相关注释与三节点一致,这里只给出分布图):
- 两个数据中心:三个成员来自数据中心 1 和数据中心 2 的两个成员。
- 如果数据中心 1 发生故障,副本集将变为只读。
- 如果数据中心 2 发生故障,副本集仍可写,因为数据中心 1 的成员可以形成多数。
- 3 个数据中心:2 个成员为数据中心 1,2 个成员为数据中心 2,1 个成员为站点数据中心 3。
- 如果任意一个数据中心发生故障,副本集仍保持可写状态,因为其余成员可以选举这样做。
例如,以下5个副本集的成员分布在三个数据中心中。
数据故障转移优先级
某些副本集成员(例如具有网络限制或资源有限的成员)不应是故障转移主要成员。将不应该是主要成员的成员设置为具有priority0。
在某些情况下,您可能希望选择一个数据中心成员作为主要成员,然后选择另一个数据中心中的成员。您可以更改优先级成员,使一个数据中心内的成员优先级高于其他数据中心内的成员。
在以下示例中,数据中心 1 副本集的成员的优先级高于数据中心 2 和 3 的成员;数据中心 2 的成员的优先级高于数据中心 3 的成员。级别:
副本集如何保证数据高可用性?
副本集如何保证数据的高可靠性?或者说它包含什么机制?这里我们从两个方面来解释:一是选举机制,二是故障转移时的回滚。
选择机制
副本集通过选择机制选择主节点。
- 如何选择主控节点?
假设副本集中可以投票的成员数为N,则多数为N/2+1。如果副本集中存活的成员数为不到大多数,整个复制。该集无法选主,副本集无法提供写服务,处于只读状态。
示例:3个投票节点需要2张节点批准票,允许投票失败次数为1次;对于5个投票节点,需要3张节点批准票,允许选举失败次数为2次;通常,投票节点的数量为奇数,这样可以减少选举失败的概率。
- 什么情况下会启动选举机制?
选择机制在以下情况下触发:
- 向副本集添加新节点
- 初始化副本集时
- 保留副本集(来自D)或 rs .reconfig()工作时
- 如果子节点失去联系,比如超时成员有投票❙10秒(默认)?哪些不是?
首先,并不是所有节点都参与投票。一个副本集最多可以有 50 个节点,但只能有 7 个投票节点。无投票节点的票数为0,即vote0;其优先级为0,即priority0。
例如: 例如: 如果成员在故障转移后重新加入其副本集,则回滚将恢复先前主数据库对数据库的写入。基本上,它保证了数据的一致性。 仅当主数据库接受在主数据库降级之前辅助数据库未复制的写入时才需要回滚。当主数据库作为辅助数据库重新加入集合时,它会恢复或“回滚”其写入,以保持数据库与其他成员一致。 Oplog(操作日志)是一个特殊的有界集合(旧日志会被覆盖),它存储所有修改数据库中存储的数据的操作的当前记录。 MongoDB在主节点上执行数据库操作,然后将这些操作记录到optlog中。然后子节点通过异步过程迭代并应用(数据同步)这些操作。在 local.oplog.rs 集合中,副本集的所有成员都包含用于维护数据库当前状态的 oplog 副本。 MongoDB 4.4 支持以小时为单位设置最短 oplog 保留期,其中 MongoDB 仅在以下情况下删除 oplog 记录: 我们来看看MongoDB在设计OptLog时考虑了什么?这对于我们使用和配置optlog时非常有用。 同步副本集中的数据用于维护共享数据集的最新副本,包括同步副本集中的次要成员或从其他成员复制数据。 。MongoDB 使用两种形式的数据同步: 如果从节点出现以下情况,必须先进行全量同步 这三种场景匹配 初始同步过程。 同时投票的节点必须处于以下状态之一:
PRIMARY
、、启动2、 恢复
、变更
、返回
全部故障转移期间回滚
复制集中的OptLog
什么是OptLog
同步副本集中的数据
Initial Synchronization(初始同步)
minvalid
_initialSyncFlag
[t1, t2]
范围内的所有 oplog
_initialSyncFlag
被清除复制(Replication)
新同步结束后,自动生成新的初始同步。从小学开始,再玩一遍”。这个过程在中学同步慢问题的分析中也有介绍过。这里是另一个角度。让我们进一步分析
- 生产者线程。该线程不断从同步源拉取oplog并添加到BlockQueue中存储。
- replBatcher线程,该线程负责从生产者线程的队列中一一提取oplog并放入其维护的队列中。
- sync线程默认将replBatcher线程队列分配给16个replWriter线程,replWriter线程最终会重播每条oplog。
问题来了,为什么“拖放日志”这么简单的操作这么难呢?
出于性能原因,oplog 获取是通过单个线程完成的。如果在pull线程中也放了重复,同步会很慢;所以生产者线程只想做一件事。
为什么不将拉取的oplog直接分发到replWriter线程,而是需要额外的replBatcher线程来进行传输呢?
Olog播放必须保持顺序,而对于createCollection、dropCollection等DDL命令,这些命令不能与其他添加、删除、修改、检查命令并行执行,而这些控制是由replBatcher执行的。 。
注意事项
- 初始同步单线程复制数据,效率比较低,生产环境应尽量避免初始同步,oplog一定要合理配置,按默认“5%可用磁盘空间”配置oplog在大多数情况下可以满足所有场景的需求。特殊情况(case1、case2)可以根据实际情况设置更大的oplog。
- 添加新节点时,可以避免与物理副本的初始同步,将主节点的dbpath复制到新节点上直接启动,效率更高。
- 当Secondary模块所需的oplog部署在同步源中时,Secondary将无法正常同步,并进入RECOVERING状态。要重新同步,您需要主动向辅助设备发送 resyc 命令。
- 在生产环境中,最好通过db.printSlaveReplicationInfo()监控主备同步延迟。如果二级滞后太远,必须及时排查原因。
- 如果辅助同步延迟是由于主数据库中的并发写入过多引起的(db.serverStatus().metrics.repl.buffer.sizeBytes 继续接近 db.serverStatus().metrics.repl.buffer.maxSizeBytes ) ,可以通过调整并发辅助系统上的replWriter线程数来改进。
复制集读写问题(关注)
读优先级(Read Preference)
默认情况下,副本集的所有读请求都会发送到primary。驱动程序可以设置读取首选项以将读取请求路由到其他节点。
primary
:默认规则,所有读请求都发送到primary secondary优先,如果所有Secondary都不可用,则请求primarynearest
:读请求发送到最近的可用发现节点(最近discovery节点)写关注默认情况下,主节点在写操作完成后返回。驱动程序可以通过指定写入问题来设置成功写入的规则。
以下写入规则指定对于大多数节点,写入必须在 5 秒超时后成功。
db.products.insert( { item: "envelopes", qty : 100, type: "Clasp" }, { writeConcern: { w: majority, wtimeout: 5000 } } )
以上设置方法为1次查询。您还可以更改副本集的默认写入问题,这样您就不必为每个请求单独设置它。
来源:https://www.pdai.tech/md/db/nosql-mongo/mongo-z-rep.htmlcfg = rs.conf() cfg.settings = {} cfg.settings.getLastErrorDefaults = { w: "majority", wtimeout: 5000 } rs.reconfig(cfg)
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。