副本集1、副本集介绍2、异步复制2.1、慢操作2.2、复制延迟和流量控制3、自动故障转移4、读取操作4.1、读取偏好4.2、数据可见性4.3、镜像读5、操作日志5.1、操作日志基础5.2、操作日志大小5.3、最短操作日志保留期5.4、可能需要更大操作日志的工作负载5.5、操作日志状态1、副本集介绍MongoDB数据库中的副本集可提供冗余并提高数据可用性是一组维护相同数据集的mongod实例。通过在不同的数据库服务器上设置数据副本副本集为单个数据库服务器丢失的情况提供了一定程度的容错能力。副本集包含多个数据承载节点和一个可选的仲裁节点。在数据承载节点中只有一个主节点其余的称为从节点。需要注意的是每个副本集节点必须属于且只属于一个副本集。副本集节点不能属于多个副本集。主节点会接收所有写入操作。副本集只能有一个可以使用{w: “majority”}写关注级别对写入请求进行确认的主节点具体如图所示。尽管在某些情况下另一个mongod实例可能会暂时将自身视为主节点。主节点在其操作日志(oplog)中记录对其数据集的所有更改。从节点复制主节点的操作日志(oplog)并将这些操作应用于其数据集以便从节点的数据集反映主节点的数据集状态。如果主节点为不可用则符合条件的从节点之间将进行选举以便选举出新的主节点具体如图所示。而在某些情况下例如当存在一个主节点和一个从节点时由于成本有限无法再添加另一个从节点​设计人员可以选择将一个mongod实例作为仲裁节点添加到副本集中。仲裁节点参与选举但不能持有数据即不提供数据冗余具体如图所示。需要注意仲裁节点将永远是仲裁节点。而在选举期间主节点可能被降级成为从节点从节点可能变为主节点。2、异步复制在MongoDB数据库的副本集中从节点会复制主节点的操作日志(oplog)并将操作异步应用于其数据集。通过使从节点的数据集反映主节点数据集的状态即使一个或多个节点出现故障副本集也可以继续运行。2.1、慢操作现在副本集的从节点会记录应用时间超过慢操作阈值的操作日志(oplog)条目。这些慢操作日志(oplog)消息包括在diagnostic log中针对从节点记录。记录在REPL组件下该组件将包含如下文本applied op:oplog entrytooknumms不依赖于日志级别系统级别或组件级别​。不依赖于分析级别。受slowOpSampleRate参数的影响。分析器不会捕获慢操作日志(oplog)条目。2.2、复制延迟和流量控制复制延迟是指主节点上的操作与将该操作从操作日志(oplog)应用到从节点之间的延迟。一些小的延迟是可以接受的但随着复制延迟的增加会出现严重的问题包括在主节点上创建缓存压力。管理员可以限制主节点应用写入的速率目标是将majority committed延迟保持在可配置的flowControlTargetLagSeconds最大值以下。默认情况下流量控制为enabled。启用流量控制后随着延迟接近flowControlTargetLagSeconds最大值主节点上的写入操作必须先获取票据然后才能获取锁以应用写入操作。通过限制每秒发出的票据数量流量控制机制将尝试将延迟保持在目标延迟以下。3、自动故障转移在MongoDB数据库的副本集中当主节点在超过配置的electionTimeoutMillis时间段默认值为10秒内未与副本集中的其他节点通信时一个符合条件的从节点将发起选举并提名自己成为新的主节点。集群将尝试完成新主节点的选举并恢复其正常运转具体如图所示。在成功完成选举之前副本集无法处理写操作。如果将读取查询配置为当主节点离线时在从节点上运行那么副本集可以继续为读取查询提供服务。假设采用默认Replica Configuration Settings副本配置设置​那么集群选举新的主节点之前的平均时间通常不应超过12秒这包括将主节点标记为不可用以及召集和完成选举所需的时间。可以通过修改settings.electionTimeoutMillis复制配置选项来调整该时间段。网络延迟等因素可能会延长副本集选举完成所需的时间这反过来又会影响集群在没有主节点的情况下运行的时间这些因素取决于具体的集群架构。将electionTimeoutMillis复制配置选项从默认的10000ms降低可以更快地检测到主节点故障。然而由于临时网络延迟等因素即使主节点在其他方面是健康的集群也可能会更频繁地进行选举。这可能导致w: 1写入操作的回滚次数增加。应用程序的连接逻辑应该包括对自动故障转移和后续选举的容忍度。MongoDB驱动程序可检测到主节点丢失并一次性自动重试某些写入操作从而为自动故障转移和选举提供额外的内置处理功能即兼容的驱动程序将默认启用可重试写入。MongoDB数据库提供了镜像读功能通过使用最近访问的数据来预热可选的从节点缓存。预热从节点的缓存有助于在选举后更快地恢复性能。4、读取操作4.1、读取偏好MongoDB数据库在默认情况下客户端会从主节点进行读取但客户端可以指定读取偏好以向从节点发送读取操作。具体如图所示。异步复制到从节点意味着在从节点读取到的数据可能不会反映主节点上数据的状态。但是包含读操作的分布式事务必须使用读取偏好指向主节点。同时给定事务中的所有操作必须路由至同一节点。4.2、数据可见性MongoDB数据库根据读关注客户端可在写入操作持久化之前看到写入结果无论写入操作的写关注级别如何对于使用local或available读关注的其他客户端均可在写入操作被发起之前看到该操作的结果。使用local或available读关注的客户端可读取数据而这些数据后续可能会在副本集故障转移期间进行回滚。对于多文档事务中的操作当进行事务提交时该事务中进行的所有数据更改都将保存并在事务外部可见。换言之一个事务不会在回滚其他事务的同时提交某些更改。在事务进行提交前在事务中所进行的数据更改在事务外不可见。不过当事务写入多个分片时并非所有外部读取操作都需等待已提交事务的结果在各个分片上可见。例如如果事务已提交并且写入1在分片A上可见但写入2在分片B上尚不可见则读关注local处的外部读取可以在不看到写入2的情况下读取写入1的结果。4.3、镜像读在MongoDB数据库中读取这类操作可减少由于中断或计划维护后主节点选举对系统的影响。在副本集发生故障转移后接管成为新主节点的从节点会在新查询请求传入时更新其缓存。在缓存预热期间性能可能会受到影响。镜像读(Mirrored Reads)会预热electable从节点副本集成员的缓存。为了预热可选举从节点的缓存主节点会将其接收到的、受支持操作的实例镜像到可选举的从节点。可以使用mirrorReads参数来配置接收镜像读的electable从节点副本集节点的子集大小。需要注意镜像读取不会影响主节点对客户端的响应。主节点镜像复制到从节点的读取是“发后即忘”类型的操作。主节点不会等待响应。镜像读取支持以下操作Count统计文档数量。Distinct返回指定字段的唯一值。Find查询文档。findAndModify支持镜像读取过滤器将作为一次镜像读取请求发送。update支持镜像读取过滤器将作为一次镜像读取请求发送。默认情况下启用镜像读并使用默认的samplingRate值为0.01​。如果要禁用镜像读可将mirrorReads参数设置为{samplingRate: 0.0}具体代码如下当采样率大于0.0时主节点将把支持的读取操作镜像复制到部分electable的从节点。当采样率为0.01时主节点会将它接收到的且受支持的读取操作的百分之一镜像复制到可参与选举的从节点。如果要更改镜像读取的采样率可以将mirrorReads参数设为[0.01.0]区间的数字具体内容如下采样率设置为0.0将禁用镜像读。当采样率介于[0.01.0]区间时主节点会按照指定的采样率随机向可参选从节点转发支持的读取操作。采样率1.0会导致主节点将所有支持的读取操作转发到可参选从节点。如果要镜像读取指标可以在下列操作中指定字段serverStatus命令和db.serverStatus()方法会返回mirroredReads指标具体代码如下db.serverStatus({mirroredReads:1})5、操作日志5.1、操作日志基础MongoDB数据库的操作日志(oplog)是一种特殊的固定大小集合用于滚动记录对数据库中存储数据的所有修改操作。如果写入操作未修改任何数据或失败则不会创建操作日志条目。与普通固定大小集合不同操作日志可能会增长到超过配置的大小限制从而避免删除majoritycommit point多数提交点​。MongoDB会对主节点应用数据库操作并在主节点的操作日志中记录这些操作。然后从节点成员会在异步流程中复制并应用这些操作。在local.oplog.rs集合中所有副本集成员均包含此操作日志的副本从而可以维持数据库的当前状态。为了便于复制所有副本集成员都会向所有其他成员发送ping消息以确认彼此的状态。任何从节点都可以从其他成员导入操作日志条目。操作日志中的每个操作都是幂等的即无论对目标数据集应用一次还是多次操作日志的操作都会产生相同的结果。5.2、操作日志大小当MongoDB数据库首次启动副本集节点时如果未指定操作日志大小MongoDB会创建默认大小的操作日志。默认的操作日志大小具有以下限制默认最小操作日志大小为990MB。如果5%的可用磁盘空间或物理内存以存储引擎为准小于990MB则默认的操作日志大小为990MB。默认最大的操作日志大小为50GB。如果5%的可用磁盘空间或物理内存根据存储引擎而定大于50GB则默认操作日志大小为50GB。在大多数情况下默认的操作日志大小是足够使用的。如果操作日志占可用磁盘空间的5%并在24小时的运行中被填满那么从节点可以长达24小时停止从操作日志复制条目并且不会由于过时太久而导致无法继续复制。然而大多数副本集的操作量要低得多它们的操作日志可以容纳更多的操作。在mongod创建操作日志之前可以使用oplogSizeMB选项指定其大小。首次启动副本集成员后使用replSetResizeOplog管理命令更改操作日志大小。我们可以使用replSetResizeOplog选项动态调整操作日志的大小而无须重启mongod进程。5.3、最短操作日志保留期在MongoDB数据库中可以指定保留操作日志条目的最小小时数。在此期间mongod仅在以下两个条件都满足时才会删除操作日志条目操作日志已达到最大配置大小。操作日志条目早于根据主机系统时钟配置的小时数。默认情况下MongoDB不设置最小操作日志保留期并自动从最旧的条目开始截断操作日志以维持配置的操作日志最大的大小。要在启动mongod时配置操作日志最短保留期可执行以下任一操作将storage.oplogMinRetentionHours设置添加到mongod配置文件中。添加–oplogMinRetentionHours命令行选项。要在正在运行的mongod上配置最短操作日志的保留期可以使用replSetResizeOplog选项。在mongod运行时设置最短操作日志的保留期会覆盖启动时设置的任何值。另外必须更新相应配置文件设置或命令行选项的值才能在服务器重启后继续保持这些更改。5.4、可能需要更大操作日志的工作负载在MongoDB数据库中如果预计副本集的工作负载类似于以下模式场景之一那么可能需要创建一个比默认值更大的操作日志。同时更新多个文档为保持幂等性操作日志必须将多次更新转换为单次操作。这会使用大量的操作日志空间而数据大小或磁盘用量并未相应增长。删除的数据量等于插入的数据量如果删除的数据量与插入的数据量大致相同则数据库的磁盘使用量不会显著上升但操作日志却可能会变得很大。大量就地更新如果工作负载的很大一部分是不会增加文档大小的更新操作则数据库会记录大量操作但不会更改磁盘上的数据量。相反如果应用程序主要执行读取操作并且仅执行少量写入操作则一个较小的操作日志可能已经足够。5.5、操作日志状态在MongoDB数据库中要查看操作日志的状态包括操作的大小和时间范围可以执行rs.printReplicationInfo()方法。在特殊情况下如要复制延迟和流量控制操作日志更新可能会依据所需的性能时间进行延迟。使用来自从节点成员的db.getReplicationInfo()和复制状态输出评估当前的复制状态并确定是否存在任何意外出现的复制延迟。管理员可以限制主节点应用写入的速率目标是majoritycommitted选项延迟保持在可配置的flowControlTargetLagSeconds最大值以下。在默认情况下流量控制设置为enabled。