[mongo] {第六部分} mongodb replication V1
复制
MongoDB中副本集是一组mongod进程,其保持相同的数据集。副本集提供了冗余和 高可用性,并且是生产部署的基础。
冗余和数据高可用性
复制提供冗余并提高 数据可用性。使用不同数据库服务器上的多个数据副本,复制可提供一定程度的容错能力,以防止单个数据库服务器故障。
在某些情况下,复制可以提供更大的读取容量,因为客户端可以将读取操作发送到不同的服务器。在不同数据中心中维护数据副本可以提高数据本地性和分布式应用程序的可用性。您还可以维护其他副本以用于专用目的,例如灾难恢复,报表或备份。
MongoDB复制
replica set是一组mongod维护相同数据集的实例。一个副本集包含多个数据承载节点和一个仲裁器节点(可选)。在数据承载节点中,只有一个成员被视为主要节点,而其他节点则被视为次要节点。
Replica Set Members
Primary:主服务器接收所有写操作。
Secondaries.辅助数据库从主数据库复制操作以维护相同的数据集。辅助服务器可能具有用于特殊用途配置文件的其他配置。例如,次级可以是 无表决权或 优先级0。
副本集的最低建议配置是具有三个数据承载成员的三个成员副本集:一个主要成员和两个次要成员。在某些情况下(例如,您有一个主服务器和一个辅助服务器,但由于成本限制,禁止添加另一个辅助服务器),您可以选择包括一个仲裁节点。仲裁节点加选举,但不保存数据(即不提供数据冗余)。
一个副本集最多可以有50个成员,但只有7个投票成员。
Primary
主节点接收所有写操作。一个副本集只能有一个主副本,能够确认具有{w: majority}写关注点的写操作;尽管在某些情况下,另一个mongod实例可能会暂时认为自己也是主副本。[1] 主服务器在其操作日志(即oplog)中记录对其数据集的所有更改。
Secondaries
二级数据库复制主数据库的oplog并将操作应用于它们的数据集,以便二级数据库的数据集反映主数据库的数据集。如果不可用,一个可用的secondary 将选举自己成为新的primary节点。
Priority 0
不能成为primary和参与 选举。
Hidden
隐藏成员维护主数据集的副本,但对客户端应用程序是不可见的。隐藏成员适用于使用模式与副本集中其他成员不同的工作负载。隐藏成员必须始终是优先级为0的成员,因此不能成为primary。 db.isMaster()不显示隐藏成员。然而,隐藏成员可以在选举中投票。
Delayed
延迟的成员包含副本集数据集的副本。但是,延迟成员的数据集反映了该集的较早或延迟的状态。例如,如果当前时间是09:52,并且成员有一个小时的延迟,则延迟的成员没有比08:52更新的操作。
由于延迟成员是数据集的“滚动备份”或运行中的“历史”快照,因此它们可以帮助从各种人为错误中恢复。例如,延迟成员可以从失败的应用程序升级和操作员错误(包括删除的数据库和集合)中恢复。
要求
延迟成员:
- 必须是 优先级为0的 成员。将优先级设置为0,以防止延迟成员成为主要成员。
- 应该是 隐藏 成员。始终阻止应用程序查看和查询延迟的成员。
- 如果members[n].votes设置为1 ,可以进行投票。
Arbiter
在某些情况下(例如您有一个主服务器和一个辅助服务器,但由于成本限制,禁止添加另一个辅助服务器),您可以选择将一个mongod实例作为仲裁节点添加到副本集 。仲裁节点参加 选举,但不保存数据(即不提供数据冗余)。
仲裁节点不可成为主节点。
Replica Set Oplog
OPLOG(操作日志)是一个特殊的固定集合(capped collection),它可将修改数据的所有操作的滚动记录存储在数据库中。
在版本4.0中进行了更改:从MongoDB 4.0开始,与其他固定集合不同,oplog可以增长超过其配置的大小限制,以避免删除大多数提交点。
版本4.4中的新增功能: MongoDB 4.4支持指定以小时为单位的最小oplog保留期限,其中MongoDB仅在以下情况下删除oplog条目:
- 操作日志已达到配置的最大大小,并且
- oplog条目早于配置的时间。
MongoDB在主数据库上应用数据库操作,然后在主数据库的操作日志中记录该操作。然后,辅助成员将这些操作复制并应用到异步过程中。所有副本集成员在local.oplog.rs集合中都包含操作日志的副本 ,这使他们可以维护数据库的当前状态。
为了促进复制,所有副本集成员都将心跳(ping)发送给所有其他成员。任何辅助成员都可以从任何其他成员导入操作日志条目。
oplog中的每个操作都是幂等的。也就是说,oplog操作会产生相同的结果,无论是一次还是多次应用于目标数据集。
Oplog大小
首次启动副本集成员时,如果未指定操作日志大小,则MongoDB会创建默认大小的操作日志。[1]
对于Unix和Windows系统
默认操作日志大小取决于存储引擎:
储存引擎 |
默认Oplog大小 |
下界 |
上界 |
In-Memory 存储引擎 |
物理内存的5% |
50MB |
50 GB |
WiredTiger存储引擎 |
可用磁盘空间的5% |
990MB |
50 GB |
对于64位macOS系统
默认操作日志大小为192 MB的物理内存或可用磁盘空间,具体取决于存储引擎:
储存引擎 |
默认Oplog大小 |
In-Memory存储引擎 |
192 MB的物理内存 |
WiredTiger存储引擎 |
192 MB的可用磁盘空间 |
在大多数情况下,默认操作日志大小已足够。例如,如果操作日志是可用磁盘空间的5%,并且在24小时的操作中已满,则辅助服务器可以在长达24小时的时间内停止从操作日志中复制条目,而不会过时而无法继续复制。但是,大多数副本集的操作量要低得多,并且它们的oplog可以容纳更多的操作。
在mongod创建操作日志之前,您可以使用oplogSizeMB选项指定其大小。首次启动副本集成员后,请使用 replSetResizeOplog管理命令更改操作日志大小。replSetResizeOplog使您能够动态调整操作日志的大小,而无需重新启动mongod进程。
4.4版的新功能:从MongoDB 4.4开始,您可以指定保留oplog条目的最小时间。该mongod只截断的OPLOG项,如果:
- 操作日志已达到配置的最大大小,并且
- 根据主机系统时钟,oplog条目比配置的小时数早。
默认情况下,MongoDB不会设置最小操作日志保留期限,而是从最早的条目开始自动截断操作日志,以维持配置的最大操作日志大小。
Oplog最小保留期限
4.4版的新功能:从MongoDB 4.4开始,您可以指定保留oplog条目的最小时间。mongod仅移除一个OPLOG,如果:
- 操作日志已达到最大配置大小,并且
- 根据主机系统时钟,oplog条目比配置的小时数早。
默认情况下,MongoDB不会设置最小操作日志保留期限,而是从最早的条目开始自动截断操作日志,以维持配置的最大操作日志大小。
要在启动时配置最小操作日志保留期 mongod,请执行以下任一操作:
- 将oplogMinRetentionHours设置添加到配置文件。
-要么-
- 添加--oplogMinRetentionHours命令行选项。
要在运行中配置最小oplog保留期限 mongod,请使用replSetResizeOplog。在mongod 运行时设置最小oplog保留期限将覆盖启动时设置的所有值。您必须更新相应的配置文件设置或命令行选项的值,以通过服务器重新启动来保留这些更改。
的工作负载大需要较大Oplog
如果您可以预测副本集的工作量类似于以下模式之一,则可能需要创建一个大于默认值的操作日志。相反,如果您的应用程序主要以最少的写操作执行读取,则较小的操作日志可能就足够了。
以下工作负载可能需要更大的oplog大小。
一次更新多个文档
操作日志必须将多次更新转换为单独的操作,以保持幂等性。这会占用大量操作日志空间,而不会相应增加数据大小或磁盘使用量。
删除等于插入的数据量
如果删除与插入时大致相同的数据量,则数据库在磁盘使用方面不会显着增长,但是操作日志的大小可能会很大。
大量更新
如果工作量的很大一部分是不增加文档大小的更新,则数据库会记录大量操作,但不会更改磁盘上的数据量。
Oplog状态
要查看操作日志状态,包括操作的大小和时间范围,请发出该rs.printReplicationInfo()方法。
数据同步
慢操作
从版本4.2开始(也可从4.0.6开始使用),副本集的辅助成员现在会记录需要比慢速操作阈值更长时间才能应用的oplog条目。这些慢oplog消息记录在REPL组件下的诊断日志中,并带有文本applied op:<oplog entry>take<num>ms。这些慢oplog条目仅取决于慢操作阈值。它们不依赖于日志级别(系统或组件级别)、分析级别或慢操作采样率。探查器不会捕获较慢的oplog条目。
复制延迟和流控制
复制延时是指将主磁盘上的写操作复制到辅助节点上的时间 。可以接受一些小的延迟时间,但是随着复制延时的增加会出现严重的问题,包括在主数据库上增加缓存压力。
从MongoDB 4.2开始,管理员可以限制主应用其写入的速率,目的是将大多数提交的延迟保持在可配置的最大值flowControlTargetLagSeconds下。
默认情况下,流控制为enabled。
注:要启用流控制,副本集/分片群集必须:featureCompatibilityVersion(FCV)是4.2版本及开启read concern majority。也就是说,如果FCV不是4.2或者如果read concern majority被禁用,那么流控制将不起作用。
在启用流控制的情况下,随着延迟接近flowControlTargetLagSeconds,主服务器上的写操作必须在获取锁以应用写操作之前获取tickets。通过限制每秒发行的tickets数量,流控制机制试图将延迟保持在目标值以下。
异步复制
辅助节点复制主节点的操作日志,并将操作异步应用于其数据集。通过使辅助数据库的数据集反映主要数据库的数据集,即使一个或多个成员失败,副本集也可以继续运行。
自动故障转移
当主节点与集合中的其他成员的通信electionTimeoutMillis时间超过配置的时间段(默认为10秒)时,可用的辅助节点将要求选举以提名自己为新的主节点。群集尝试完成新主数据库的选择并恢复正常操作。
副本集无法处理写入操作,直到选举成功完成。如果将副本集配置为在主副本处于脱机状态时在次副本上运行,则副本集可以继续提供读取查询 。
假设默认的副本配置设置,集群选择新主服务器之前的平均时间通常不应超过12秒。这包括将初选标记为不可用、调用和完成选举所需的时间。您可以通过修改settings.electionTimeoutMillis设置复制配置选项。诸如网络延迟之类的因素可能会延长完成副本集选择所需的时间,进而影响群集在没有主服务器的情况下运行的时间。这些因素取决于特定的集群体系结构。
将electionTimeoutMillis复制配置选项从默认值10000(10秒)降低可以更快地检测主故障。然而,由于诸如临时网络延迟之类的因素,集群可能更频繁地调用选举,即使主节点在其他方面是健康的。这可能导致w:1写操作的回滚增加。
应用程序连接逻辑应包括对自动故障切换和后续选择的容忍度。从MongoDB 3.6开始,MongoDB可以检测到主设备的丢失,并自动重试某些写入操作一次,从而提供自动故障切换和选择的额外内置处理:
- 与MongoDB 4.2兼容的驱动程序默认情况下启用重试写入
- 与MongoDB 4.0和3.6兼容的驱动程序必须通过retryWrites=true在连接字符串中包含来显式启用可重试的写入。
从4.4版开始,MongoDB提供镜像读取,以使用最近访问的数据预热可选举的次要成员的缓存。预热辅助服务器的缓存可以帮助在选举后更快地恢复性能。
Write Concern
副本集的Write concern描述了在操作返回成功之前必须确认写操作的数据承载成员(即主要成员和次要成员,但不是仲裁节点)的数量。成员只能在成功接收并应用写操作之后才确认写操作。
对于副本集,w:1的默认Write concern要求只有主副本集成员在返回写入关注点确认之前确认写入。您可以指定一个大于1的整数值,以要求主副本进行确认,并根据需要指定多个辅助副本来满足指定的值,最多为副本集中承载数据的成员总数。
Write concern为“majority”的写入操作要求确认写入操作已传播到数据承载投票成员的计算多数。对于成员已启用日志记录的集群,将“majority” Write concern与j:true结合可以防止Write concern确认后的数据的回滚。
读取操作
Read Preference
默认情况下,应用程序将其读取操作定向到副本集中的 primary 成员(即读取首选项模式“ primary ”)。但是,客户端可以指定读取首选项,以将读取操作发送到辅助对象。
读取首选项模式 |
描述 |
primary |
默认模式。所有操作均从当前副本集primary中读取 。 包含读取操作的多文档事务必须使用读取首选项primary。给定事务中的所有操作都必须路由到同一成员。 |
primaryPreferred |
在大多数情况下,操作从主服务器读取,但如果不可用,则从辅助 成员读取操作。 从版本4.4开始,primaryPreferred支持分片 群集上的树篱读取。 |
secondary |
所有操作均从副本集的辅助成员读取。 从版本4.4开始,secondary支持分片 群集上的树篱读取。 |
secondaryPreferred |
在大多数情况下,操作从辅助 成员读取,但是如果没有辅助成员可用,则操作从分片群集的主成员读取。 从版本4.4开始,secondaryPreferred支持分片 群集上的树篱读取。 |
nearest |
基于指定的等待时间阈值,从随机的合格副本集 成员读取操作,而不管该成员是主要副本 还是次要副本。该操作在计算延迟时会考虑以下因素:
从版本4.4开始,nearest支持分片 群集上的树篱读取,并且默认情况下启用树篱读取选项。 |
异步复制到辅助数据库意味着从辅助数据库读取数据可能会返回不反映主数据库上数据状态的数据。
多文档事务的读取必须使用read preference primary。给定事务中的所有操作都必须路由到同一成员。
数据可见性
根据读取的关注点,客户端可以在持久写入之前看到写入的结果:
- 不管 write concern,其他使用"local"或"available" read concern的客户端都可以在向发布客户端确认写操作之前看到写操作的结果。
- 使用"local"或"available" read concern的客户端可以读取数据,这些数据随后可能会在副本集故障转移期间回滚。
对于多文档事务中的操作,在提交事务时,将保存在事务中进行的所有数据更改,并在事务外部可见。也就是说,事务在回滚其他事务时将不会提交更改。
在提交事务之前,在事务外部看不到在事务中进行的数据更改。
但是,当一个事务写入多个分片时,并非所有外部读取操作都需要等待提交的事务的结果在分片中可见。例如,如果事务已提交,并且write 1在shard a上可见,但write 2在shard B上尚不可见,则外部read concern “local”可以读取write 1的结果,而不会看到write 2。
镜像读取
从版本4.4开始,MongoDB提供镜像读取来预热可选辅助成员(即优先级大于0的成员)的缓存。使用镜像读取(默认情况下启用),主服务器可以镜像它接收的操作子集,并将它们发送到可选择的辅助服务器子集。子集的大小是可配置的。
注意:
主服务器对客户端的响应不受镜像读取的影响。镜像读取是由主服务器执行的“fire-and-forget”操作;即,主服务器不等待镜像读取的响应。
支持的操作
以下操作支持镜像读取:
- count
- distinct
- find
- findAndModify (特别是,过滤器作为镜像读取发送)
- update (特别是,过滤器作为镜像读取发送)
启用/禁用支持镜像读取
在MongoDB 4.4中,默认情况下启用镜像读取,并使用默认采样率0.01。也就是说,主镜像以1%的采样率读取每个可选(即优先级大于0)次镜像。
例如,给定一个副本集,该副本集有一个主副本和两个可选的辅助副本,采样率为0.01,如果主副本接收到100个可以镜像的操作,则采样可能导致1个读取镜像到一个辅助副本,0个读取镜像到另一个副本,或0个读取镜像到每个副本,以此类推。
要修改采样率,请使用mirrorReads参数:
- 采样率值0.0禁用镜像读取。
- 大于0.0启用镜像读取的采样率。
- 采样率不能大于1.0。
镜像读取指标
从MongoDB 4.4开始,如果您在操作中指定了字段的包含内容,则该命令serverStatus及其相应的mongoshell方法将 db.serverStatus()返回mirroredReads。例如,
db.serverStatus( { mirroredReads: 1 } )
事务
从MongoDB 4.0开始,多文档事务可用于副本集。
多文档事务的读取必须使用read preference primary。给定事务中的所有操作都必须路由到同一成员。
在提交事务之前,在事务外部看不到在事务中进行的数据更改。
但是,当一个事务写入多个分片时,并非所有外部读取操作都需要等待提交的事务的结果在分片中可见。例如,如果事务已提交,并且write 1在shard a上可见,但write 2在shard B上尚不可见,则外部read concern “local”可以读取write 1的结果,而不会看到write 2。
Change Streams
从MongoDB 3.6开始,change streams可用于副本集和分片群集。change streams允许应用程序访问实时数据更改,而不会带来复杂性和拖延操作日志的风险。应用程序可以使用change streams来订阅一个或多个集合上的所有数据更改。
附加功能
副本集提供了许多选项来支持应用程序需要。例如,您可以在多个数据中心部署具有成员的副本集,或者通过调整某些成员的成员[n].优先级来控制选举结果。副本集还支持用于报告、灾难恢复或备份功能的专用成员。
rs.status()
从运行方法的成员的角度返回副本集状态。此方法为replSetGetStatus命令提供了包装 。
此输出使用从副本集其他成员发送的心跳数据包派生的数据反映副本集的当前状态。
- 点赞
- 收藏
- 关注作者
评论(0)