分片集群负载均衡器
MongoDB 负载均衡器是一个后台进程,用于监控每个分片集合的每个分片上的数据量。当给定分片上的分片集合的数据量达到特定迁移阈值时,负载均衡器会尝试在分片之间自动迁移数据,并在遵从区域的前提下实现每个分片的数据量均衡。默认情况下,负载均衡器进程始终处于启用状态。
分片集群的均衡过程对用户和应用程序层是完全透明的,不过在执行过程中可能会对性能产生一些影响。
负载均衡器在配置服务器副本集 (CSRS) 的主节点上运行。
要为单个集合配置集合均衡,请参阅 configureCollectionBalancing
。
要管理分片集群负载均衡器,请参阅管理分片集群负载均衡器。
负载均衡器内部
范围迁移会在带宽和工作负载方面产生一些开销,这两者都会影响数据库性能。负载均衡器会尝试通过以下方式尽量减少影响:
在任何给定的时间将分片限制为最多进行一次迁移。具体而言,一个分片不能同时参与多个数据迁移。负载均衡器一次迁移一个范围。
MongoDB 可以并行执行数据迁移,但一个分片一次只能参与最多一个迁移。对于具有 n 个分片的分片集群,MongoDB 可以执行最多 n/2(四舍五入)个并行迁移。
另请参阅异步范围迁移清理。
只有当分片集合中数据量最多的分片与此集合中数据量最少的分片之间的数据量差异达到迁移阈值时,才会开始一个均衡回合。
您可以暂时禁用负载均衡器以进行维护,但长时间禁用负载均衡器可能会降低集群性能。 有关更多信息,请参阅禁用负载均衡器。
您还可以限制负载均衡器的运行时间窗口,以防止它影响生产流量。有关详细信息,请参阅安排均衡窗口。
注意
均衡窗口是相对于配置服务器副本集主节点的本地时区而指定的。
在集群中添加和删除分片
向集群添加分片会造成不平衡,因为新分片没有任何数据。虽然 MongoDB 会立即开始向新的分片迁移数据,但集群可能需要一些时间才能达到平衡。有关如何向集群添加分片的说明,请参阅向集群添加分片教程。
提示
如果您的应用程序符合开始之前的要求,则可以使用reshardCollection
命令在集群中重新分发数据以包含新分片。 此进程比替代范围迁移过程快得多。
有关示例,请参阅将数据重新分发到新分片。
从集群删除分片也会造成类似的不均衡,因为驻留在该分片的数据必须在整个集群重新分布。虽然 MongoDB 会立即开始清空已删除的分片,但集群均衡可能需要一些时间。在此进程中,请勿关闭与已删除分片关联的服务器。
当您从集群中删除数据段分布不均匀的分片时,负载均衡器首先从要清空的分片中删除数据段,然后均衡剩余的不均匀数据段分布。
有关从集群安全删除分片的说明,请参见从集群删除分片教程。
范围迁移步骤
所有范围迁移都使用以下过程:
负载均衡器进程将
moveRange
命令发送到源分片。源分片收到内部
moveRange
命令时开始移动。在迁移进程中,对范围的操作将发送到源分片。源分片负责接收范围的写操作。目标分片会生成源所需要但在目标上不存在的任何索引。
目标分片开始请求该范围内的文档并开始接收数据的副本。另请参阅范围迁移和复制。
在接收到范围的最终文档之后,目标分片启动同步进程,确保其拥有在迁移过程中对迁移文档所做的更改。
完全同步后,源分片连接配置数据库,并使用范围的新位置更新集群元数据。
源分片完成元数据更新后,一旦范围内没有打开的游标,源分片就会删除其文档副本。
注意
如果负载均衡器需要从源分片执行额外的数据块迁移,那么负载均衡器可以开始下一个数据块迁移,无需等待当前迁移进程完成此删除步骤。请参阅异步范围迁移清理。
警告
具有迁移的分片集群中的从节点读取可能会丢失文档
如果正在进行迁移,分片集群中长时间运行的二次读取可能会丢失文档。
在数据块迁移期间删除数据块之前,MongoDB 会等待 orphanCleanupDelaySecs
,或与该数据块有关的正在进行的查询在分片节点上完成,以时间较长者为准。最初在主节点上运行的查询,如在该节点降级为从节点后继续执行,将被视为最初在从节点上执行。也就是说,服务器仅在当前主数据库上没有针对数据块的查询时等待 orphanDelayCleanupSecs
。
如果这些查询花费的时间超过 orphanCleanupDelaySecs
,则以数据块为目标并在从节点上运行的查询可能会错过文档。
迁移阈值
为了最大限度地减少均衡对集群的影响,负载均衡器仅在分片集合的数据分布达到特定阈值后才开始均衡。
如果分片之间的数据差异(对于该集合)小于该集合配置范围大小的三倍,则该集合被认为是均衡的。如果默认范围大小为 128MB
,两个分片对于给定集合的数据大小必须至少相差 384MB
,才能进行迁移。
异步范围迁移清理
为了从分片中迁移数据,负载均衡器会一次迁移一个范围的数据。不过,负载均衡器不会等待当前迁移的删除阶段完成才开始迁移下一个范围。有关范围迁移过程和删除阶段,请参阅范围迁移。
这种排队行为支持分片在集群严重失衡的情况下更快地卸载数据,例如在不进行预分割的情况下执行初始数据加载时以及添加新分片时。
此行为还会影响 moveRange
命令,使用 moveRange
命令的迁移脚本可能会执行得更快。
在某些情况下,删除阶段可能会持续更长时间。范围迁移得到增强,在删除阶段发生故障转移时更具弹性。即使副本集的主节点在此阶段崩溃或重启,孤立文档也会被清除。
_waitForDelete
负载均衡器设置可以更改行为,以便当前迁移的删除阶段阻止下一个数据段迁移开始。_waitForDelete
通常用于内部测试目的。有关更多信息,请参阅等待删除。
注意
范围删除是一项资源密集型操作,当集群删除文档时,可能会导致严重的缓存和 I/O 压力。
如果计划移动大量数据,例如将分片添加到集群时或将分分片的集合初始分发到多个分片期间,请考虑对集合进行重新分片。重新分片操作不需要范围清理,因此对集群的压力要小得多。
范围迁移和复制
在范围迁移过程中,_secondaryThrottle
值决定何时继续迁移范围内的下一个文档。
在 config.settings
集合中:
如果将负载均衡器的
_secondaryThrottle
设置为写关注,则在范围迁移期间,每个移动的文档都必须收到请求的确认,才能继续处理下一个文档。如果未进行
_secondaryThrottle
设置,迁移过程不会等待复制到从节点,而是继续处理下一个文档。
要更新负载均衡器的 _secondaryThrottle
参数,请参阅辅助限制示例。
某些范围迁移阶段具有以下复制策略,与任何 _secondaryThrottle
设置无关:
在使用范围位置更新配置服务器之前,MongoDB 短暂暂停对源分片上要迁移到的集合执行的所有应用程序读取和写入。MongoDB 在更新后恢复应用程序读取和写入。在将范围移动提交到配置服务器之前和之后,范围移动要求大多数副本集节点确认所有写入。
当传出迁移完成并进行清理时,必须将所有写入复制到大多数服务器,才能继续进行进一步的清理(从其他传出迁移)或新的传入迁移。
要更新 config.settings
集合的 _secondaryThrottle
设置,请参阅辅助限制示例。
每个迁移范围的最大文档数量
默认情况下,如果一个范围中的文档数大于配置的范围大小除以平均文档大小的结果的 2 倍,则 MongoDB 无法移动该范围。如果 MongoDB 可以移动数据段的子范围并将大小减小到小于该值,则负载均衡器可以迁移范围以实现该目的。db.collection.stats()
包括 avgObjSize
字段,它表示集合中的平均文档大小。
对于太大而无法迁移的数据块:
负载均衡器设置
attemptToBalanceJumboChunks
允许负载均衡器迁移太大而无法移动的数据段,只要这些数据段未标记为 jumbo。有关详情,请参阅超出大小限制的负载均衡范围。在发出
moveRange
和moveChunk
命令时,可以指定 forceJumbo 选项以允许迁移太大而无法移动的范围。范围可能标记为巨大,也可能未标记为巨大。
范围删除性能调整
您可以使用 rangeDeleterBatchSize
、rangeDeleterBatchDelayMS
和 rangeDeleterHighPriority
参数调整范围删除对性能的影响。例如:
要限制每批删除文档的数量,您可以将
rangeDeleterBatchSize
设置为较小的值,如32
。要在批量删除之间添加额外的延迟,您可以将
rangeDeleterBatchDelayMS
设置为高于当前默认值(20
毫秒)。要确定范围删除的优先级,您可以将
rangeDeleterHighPriority
设置为true
。范围删除可能是长时间运行的后台任务,在系统负载较高时,可能会对用户操作吞吐量造成不利影响。
注意
如果正在对要删除的集合执行读取操作,或者在该集合上具有打开的游标,则可能无法继续执行范围删除过程。
变更流和孤立文档
分片大小
默认情况下,随着数据集增长,MongoDB 会尝试用每个分片的数据填充所有可用的磁盘空间。要确保集群始终有能力处理数据增长,请监控磁盘使用情况以及其他性能指标。
有关设置分片最大大小的说明,请参阅更改给定分片的最大存储大小教程。
数据段大小和负载均衡
有关 chunkSize
简介,请参阅修改分片集群中的范围大小。
下表描述了 chunkSize
如何影响不同 MongoDB 版本中的碎片整理和负载均衡器操作。
MongoDB 版本 | 说明 |
---|---|
MongoDB 6.0 和更高版本 | 在两个分片之间共享的集合数据差异为配置的 例如,如果 |
早于 MongoDB 6.0 | 在数据段增长到超过 chunkSize 时,将拆分数据段。 |
在移动、分割或合并数据段时,分片元数据会在配置服务器提交数据段操作后更新。未参与数据段操作的分片也会使用新的元数据更新。
分片元数据更新时间与路由表大小成正比。在更新分片元数据时,将暂时阻止对集合的 CRUD 操作,较小的路由表意味着更短的 CRUD 操作延迟。
对集合进行碎片整理可以减少数据段数量以及更新数据段元数据的时间。
要减少系统工作负载,请使用分片负载均衡窗口将负载均衡器配置为仅在特定时间运行。碎片整理在负载均衡窗口时间段内运行。
您可以使用 chunkDefragmentationThrottlingMS
参数限制负载均衡器运行的拆分和合并命令的速率。
您可以随时启动和停止碎片整理。
您还可以设置分片区域。分片区域基于分片键,您可以将每个区域与集群中的一个或多个分片相关联。
从 MongoDB 6.0 开始,分片集群仅在必须迁移数据段时才拆分数据段。这意味着,数据段大小可能会超过 chunkSize
。较大的数据段将减少分片上的数据段数量并提高性能,因为减少了更新分片元数据的时间。例如,即使您已将 chunkSize
设置为 256 MB,您也可能会在分片上看到 1 TB 数据段。
chunkSize
影响以下内容:
在单个数据段迁移操作中,负载均衡器尝试在两个分片之间迁移的最大数据量。
碎片整理期间迁移的数据量。
有关对分片集合进行碎片整理的详细信息,请参阅对分片集合进行碎片整理。