复制
MongoDB 中的副本集是一组维护相同数据集的 mongod
进程。副本集提供冗余和高可用性,是所有生产部署的基础。本部分将介绍 MongoDB 中的副本以及副本集的组件和架构。本部分还提供了与副本集相关的常见任务教程。
您可以在用户界面中部署副本集来为您的部署实例服务,该实例将托管于 MongoDB Atlas 中。
冗余和数据可用性
复制可提供冗余并提高数据可用性。通过在不同的数据库服务器上设置数据副本,复制为单个数据库服务器丢失的情况提供了一定程度的容错能力。
在某些情况下,复制可以提供更多的读取容量,因为客户端可以将读取请求发送到不同的服务器。在不同数据中心维护数据副本可以提高分布式应用程序的数据局部性和可用性。您还可以根据特定目的维护额外的副本,如灾难恢复、报告或备份。
MongoDB 中的复制
副本集是一组维护相同数据集的 mongod
实例。副本集包含多个数据承载节点和一个可选的仲裁节点。在数据承载节点中,只有一个主节点,其他被为从节点。
警告
每个副本集节点必须属于且只属于一个副本集。副本集节点不能属于多个副本集。
主节点会接收所有写入操作。副本集只能有一个可以使用 { w: "majority" }
写关注(write concern)级别对写入请求进行确认的主节点;尽管在某些情况下,另一 mongod 实例可能会暂时将自身视为主节点。[1] 主节点在其操作日志(即 oplog)中记录对其数据集的所有更改。有关主节点操作的更多信息,请参阅副本集主节点。
从节点复制主节点的 oplog,并将这些操作应用于其数据集,以便从节点的数据集反映主节点的数据集状态。如果主节点不可用,则某个符合条件的从节点将进行选举,以将自己选举为新的主节点。有关从节点的更多信息,请参阅副本集从节点。
在某些情况下(例如存在一个主节点和一个从节点,但由于成本有限无法再添加另一个从节点),您可以选择将一个 mongod
实例作为仲裁节点添加到副本集中。仲裁节点参与选举,但不持有数据(即不提供数据冗余)。有关仲裁节点的更多信息,请参阅副本集仲裁节点。
异步复制
从节点会复制主节点的 oplog 并将操作异步应用于其数据集。通过使从节点的数据集反应主节点数据集的状态,即便一个或多个节点出现故障,副本集也可继续运行。
有关复制机制的更多信息,请参阅副本集 Oplog 和副本集数据同步。
慢操作
现在,副本集的从节点会记录应用时间超过慢操作阈值的 oplog 条目。这些慢 oplog 消息:
在
diagnostic log
中针对从节点记录。记录在
REPL
组件下,该组件将含有文本applied op: <oplog entry> took <num>ms
。不依赖日志级别(系统级别或组件级别)
不依赖于分析级别。
受
slowOpSampleRate
影响。
分析器不会捕获慢 oplog 条目。
复制延迟和流量控制
复制延迟是指主节点上的操作与将该操作从 oplog 应用到从节点之间的延迟。一些小的延迟是可以接受的,但随着复制延迟的增加,会出现严重的问题,包括在主节点上创建缓存压力。
管理员可以限制主节点应用写入的速率,目标是将 majority
committed
延迟保持在可配置的最大 flowControlTargetLagSeconds
值以下。
默认情况下,流量控制为 enabled
。
注意
为了进行流量控制,副本集/分片分片集群必须具有:featureCompatibilityVersion (FCV) 和读关注(read concern) 4.2
majority enabled
。也就是说,如果FCV不是4.2
或已禁用读关注(read concern)多数,则启用的流量控制不起作用。
启用流量控制后,随着延迟接近 flowControlTargetLagSeconds
,主节点上的写入操作必须先获取票据,然后才能获取锁以应用写入操作。通过限制每秒发出的票据数量,流量控制机制将尝试将延迟保持在目标延迟以下。
自动故障转移
当主节点在超过配置的 electionTimeoutMillis
时间段(默认 10 秒)内未与副本集中的其他节点通信时,一个符合条件的从节点将发起选举,并提名自己成为新的主节点。集群将尝试完成新主节点的选举并恢复其正常运转。
在成功完成选举之前,副本集无法处理写操作。如果将读取查询配置为当主节点离线时在从节点上运行,那么副本集可以继续为读取查询提供服务。
假设采用默认 replica
configuration settings
(副本配置设置),那么集群选举新的主节点之前的平均时间通常不应超过 12 秒。这包括将主节点标记为不可用以及召集和完成选举所需的时间。可以通过修改 settings.electionTimeoutMillis
复制配置选项来调整该时间段。网络延迟等因素可能会延长副本集选举完成所需的时间,这反过来又会影响集群在没有主节点的情况下运行的时间。这些因素取决于具体集群架构。
将 electionTimeoutMillis
复制配置选项从默认的 10000
(10 秒)降低,可以更快地检测到主节点故障。然而,由于临时网络延迟等因素,即使主节点在其他方面是健康的,集群也可能会更频繁地进行选举。这可能导致 w: 1 写入操作的回滚次数增加。
您的应用程序连接逻辑应包括对自动故障转移和后续选举的容忍度。MongoDB 驱动程序可检测到主节点丢失,并一次性自动重试某些写入操作,从而为自动故障转移和选举提供额外的内置处理功能:
兼容的驱动程序将默认启用可重试写入
MongoDB 提供镜像读功能,用最近访问的数据预热可选从节点缓存。预热从节点的缓存有助于在选举后更快地恢复性能。
要了解有关 MongoDB 故障转移进程的更多信息,请参阅:
读取操作
读取偏好
默认情况下,客户端从主节点 [1] 读取;但是,客户端可以指定读取偏好以向从节点发送读取操作。
异步复制到从节点意味着在从节点读取到的数据可能不会反映主节点上数据的状态。
包含读操作的分布式事务必须使用读取偏好 primary
。给定事务中的所有操作必须路由至同一节点。
有关从副本集读取的信息,请参阅读取偏好。
数据可见性
根据读关注,客户端可在写入操作持久化之前看到写入结果:
无论写入操作的写关注级别如何,使用
"local"
或"available"
读关注(read concern)的其他客户端均可在写入操作被发起它的客户端确认之前,看到该操作的结果。使用
"local"
或"available"
读关注的客户端可读取数据,而这些数据后续可能会在副本集故障转移期间进行回滚。
对于多文档事务中的操作,当事务提交时,该事务中进行的所有数据更改都将保存并在事务外部可见。换言之,一个事务不会在回滚其他事务的同时提交某些更改。
在事务进行提交前,在事务中所做的数据更改在事务外不可见。
不过,当事务写入多个分片时,并非所有外部读取操作都需等待已提交事务的结果在各个分片上可见。例如,如果事务已提交并且写入 1 在分片 A 上可见,但写入 2 在分片 B 上尚不可见,则读关注 "local"
处的外部读取可以在不看到写入 2 的情况下读取写入 1 的结果。
有关 MongoDB 读取隔离性、一致性和新近度的更多信息,请参阅读取隔离性、一致性和新近度。
镜像读取 (Mirrored Reads)
镜像读取可减少由于中断或计划维护后主节点选举对系统的影响。在副本集发生故障转移后,接管成为新主节点的从节点会在新查询请求传入时更新其缓存。在缓存预热期间,性能可能会受到影响。
镜像读会预热 electable
从节点副本集成员的缓存。为了预热可选举从节点的缓存,主节点会将其接收到的受支持操作的示例镜像到可选举的从节点。
可以使用 mirrorReads
参数来配置接收镜像读的 electable
从节点副本集节点的子集的大小。有关更多详细信息,请参见启用/禁用对镜像读的支持。
注意
镜像读取不会影响主节点对客户端的响应。主节点镜像复制到从节点的读取是“发后即忘”类型的操作。主节点不会等待响应。
支持的操作
镜像读取支持以下操作:
findAndModify
(具体来说,过滤器将作为一次镜像读取请求发送)update
(具体来说,过滤器将作为一次镜像读取请求发送)
启用/禁用对镜像读取的支持
默认情况下启用镜像读并使用默认的 sampling rate
(值为 0.01
)。要禁用镜像读,请将 mirrorReads
参数设置为 {
samplingRate: 0.0 }
:
db.adminCommand( { setParameter: 1, mirrorReads: { samplingRate: 0.0 } } )
当采样率大于 0.0
时,主节点将把支持的读取操作镜像复制到一部分 electable
的从节点。当采样率为 0.01
时,主节点会将它接收到且受支持的读取操作的百分之一镜像复制到可参与选举的从节点。
例如,考虑一个副本集,其由一个主节点和两个可参选的从节点组成。如果主节点接收到 1000
个可镜像复制的操作,且采样率为 0.01
,那么主节点会将大约 10
个受支持的读取操作镜像复制到可参选的从节点。每个可参选的从节点只接受 10 个读取请求中的一小部分。主节点将把每个镜像读取请求随机发送到非空的可参选从节点。
更改镜像读取的采样率
要更改镜像读取的采样率,请将 mirrorReads
参数设为 0.0
和 1.0
之间的数字:
采样率设置为
0.0
将禁用镜像读。采样率介于
0.0
和1.0
之间时,主节点会以指定的采样率向可参选从节点随机转发支持的读取操作。采样率
1.0
会导致主节点将所有支持的读取操作转发到可参选从节点。
有关详细信息,请参阅mirrorReads
。
镜像读取指标
如果您在下列操作中指定以下字段,serverStatus
命令和 db.serverStatus()
Shell 方法会返回 mirroredReads
指标:
db.serverStatus( { mirroredReads: 1 } )
事务
多文档事务可用于副本集。
包含读操作的分布式事务必须使用读取偏好 primary
。给定事务中的所有操作必须路由至同一节点。
在事务进行提交前,在事务中所做的数据更改在事务外不可见。
不过,当事务写入多个分片时,并非所有外部读取操作都需等待已提交事务的结果在各个分片上可见。例如,如果事务已提交并且写入 1 在分片 A 上可见,但写入 2 在分片 B 上尚不可见,则读关注 "local"
处的外部读取可以在不看到写入 2 的情况下读取写入 1 的结果。
Change Streams
变更流可用于副本集和分片的集群。 变更流允许应用程序访问权限实时数据更改,而不会出现oplog的复杂性和风险。 应用程序可以使用变更流订阅一个或多个集合上的所有数据更改。
其他功能
副本集可提供多个选项来支持应用程序需求。例如,您可以部署一个副本集,而其节点位于多个数据中心,或是通过调整某些节点的 members[n].priority
来控制选举结果。副本集还支持用于报告、灾难恢复或备份功能的专门节点。
请参阅优先级为 0 的副本集节点、隐藏副本集节点和延时副本集节点,以了解更多信息。
[1] | (1, 2) 在某些情况下,副本集中的两个节点可能会暂时都认为自己是主节点,但最多只有一个节点能完成 { w:
"majority" } 写关注的写入操作。能够完成 { w: "majority" } 写入操作的节点是当前的主节点,另一个节点是尚未意识到自己已降级(通常由于网络分区)的前主节点。发生这种情况时,即使已请求了读取偏好为 primary ,连接到前主节点的客户端依然可能观察到过时的数据,并且对前主节点的新的写入操作最终将被回滚。 |