MongoDB~分片数据存储Chunk;其迁移原理、影响,以及避免手段

devtools/2024/9/22 17:43:05/

分片数据存储:Chunk存储

Chunk(块) 是 MongoDB 分片集群的一个核心概念,其本质上就是由一组 Document 组成的逻辑数据单元。每个 Chunk 包含一定范围片键的数据,互不相交且并集为全部数据。

分片集群不会记录每条数据在哪个分片上,而是记录 Chunk 在哪个分片上,以及这个 Chunk 包含哪些分片键数据。

在这里插入图片描述
如上图,假设集合的shardKey x(以范围分片为例,哈希分片类似),写入该集合的文档根据其x的取值范围,会被分散到chunk1到chunk4中,每个chunk只包含特定范围的数据(比如chunk2就只包含x的取值在[-75, 25)范围内的文档),同一份chunk的文档只会存储在一个shard上,一个shard可能包含多个chunk,chunk会触发迁移,但具体存储在哪个shard,由记录在config server中的路由信息决定。

Chunk分裂

默认情况下,一个 Chunk 的最大值默认为 64MB(可调整,取值范围为 1~1024 MB。如无特殊需求,建议保持默认值),进行数据插入、更新、删除时,如果此时 Mongos 感知到了目标 Chunk 的大小或者其中的数据量超过上限,则会触发 Chunk 分裂
在这里插入图片描述

Chunk迁移

数据的增长会让 Chunk 分裂得越来越多。这个时候,各个分片上的 Chunk 数量可能会不平衡。Mongos 中的 均衡器(Balancer) 组件就会执行自动平衡,尝试使各个 Shard 上 Chunk 的数量保持均衡,这个过程就是 再平衡(Rebalance)。默认情况下,数据库和集合的 Rebalance 是开启的。

如下图所示,随着数据插入,导致 Chunk 分裂,让 AB 两个分片有 3 个 Chunk,C 分片只有一个,这个时候就会把 B 分配的迁移一个到 C 分片实现集群数据均衡。
在这里插入图片描述

Balancer 是 MongoDB 的一个运行在 Config Server 的 Primary 节点上(自 MongoDB 3.4 版本起)的后台进程,它监控每个分片上 Chunk 数量,并在某个分片上 Chunk 数量达到阈值进行迁移。

balancer通过特定规则来筛选出来需要进行迁移的chunk,这些规则具体是什么呢?当前,mongoDB会对以下三种类型的chunk进行迁移(优先级由高到底):

  1. chunk属于正在进行排水(即draining,一般出现在shard删除,move primary等情况下,表示该chunk需要尽快被删除)的shard

  2. chunk是否违反了zones的约束

  3. 如果不属于以上两种情况,则通过计算各个shard之间的chunks数量进行负载均衡,原则上balancer会让各个shard在满足zones约束的条件下尽可能均衡

选定了需要迁移的chunk后,balancer会选择当前shards中chunks数最少的一个作为迁移的目标。

Chunk 只会分裂,不会合并,即使 chunkSize 的值变大。

Rebalance 操作是比较耗费系统资源的,我们可以通过在业务低峰期执行:预分片或者设置 Rebalance 时间窗等方式来减少其对 MongoDB 正常使用所带来的影响。

Chunk迁移原理

chunk迁移操作通过moveChunk命令发起,moveChunk命令即可以被balancer自动调用(balancer每隔10s扫描哪些chunk需要被迁移),也支持用户主动发起

迁移chunk的整个过程实际上就是一次两个shard进行数据交换的过程,发送chunk的一方称为发送方(donorShard),接收chunk的一方称为接收方(recipientShard)。发送方和接收方通过一系列精心设计的步骤来实现chunk的迁移。

完成一次chunk迁移需要进行以下8个步骤:

  1. 发送方发起迁移: configsvr向发送方请求进行指定chunk的迁移任务(同一时刻只能执行一个chunk迁移)。如果此时发现已有一个相同的chunk的迁移任务,跳过此次迁移,否则会新发起一个迁移任务。
  2. 接收方发起chunk拷贝: 发送方进行迁移参数的校验,校验通过后,向接收方发送recvChunkStart命令,接收方进行一些传送文档数据的初始化工作后,会不断重复地向发送方发送migrateClone命令批量拉取chunk中的文档并将拉取的文档进行批量插入,即进行文档的全量拷贝。
  3. 接收方同时拉取增量修改: 文档全量拷贝完成后,接收方通过不断重复发送transferMods命令拉取chunk的增量修改(包括插入、更新、删除),并将其应用到自身。
  4. 发送方等待接收方chunk拷贝完成: 发送方不断向接收方发送 recvChunkStatus命令查询文档存量数据,以及增量同步是否完成或超时,当增量同步完成时,表示此时接受方已进入“steady”状态,可以进行接下来的流程。
  5. 发送方进入临界区: 一旦当接收方的文档数据同步完成,发送方就会进入临界区(critical section),此时发送方接下来的操作不可被打断,并且所有发送方的写操作将被挂起,直到发送方退出临界区。
  6. 接收方执行commit: 发送方进入临界区后,接下来会同步地调用recvChunkCommit命令给接收方,接收方再一次进行chunk文档的增量同步,同步完成后,向接收方返回同步完成的结果,接收方退出临界区,将挂起的写请求进行重定向。
  7. configsvr执行commit: 接收方收到同步完成的结果后,向configsvr发送configsvrCommitChunkMigration命令,表示迁移完成。(configsvrCommitChunkMigration命令返回前,发送方的读操作会被挂起)
  8. 当chunk迁移完成后,发送方还需要清理残留的chunk,这种chunk称之为孤儿chunk,孤儿chunk中的文档称为孤儿文档。一般情况孤儿chunk的删除是异步执行的(迁移完成后15分钟),每次删除128个文档,每次间隔20ms;但也可以指定waitForDelete在迁移流程中同步对孤儿chunk进行删除。 实际删除孤儿chunk前,需要判断该chunk是否能被删除

Chunk迁移的影响

性能影响

chunk迁移操作其实和普通的读写操作并无差别,虽然在迁移过程中MongoDB通过读写操作批量化一定程度上减轻了迁移的开销,但由于迁移操作是chunk级别的并发,且存在大量密集的写入和删除操作,如果恰好遇到业务高峰或累积了大量chunk需要迁移,对于性能还是有不小的影响。

MongoDB执行完一次chunk迁移,如果在之后不久刚好触发孤儿chunk的延迟删除,删除操作导致了多个次要节点的cache升高,由于节点规格较小,cache很快就超过20%,此时WT引擎会优先进行cahce evict操作进行内存释放,频繁的内存释放操作阻塞了读写,最终导致该secondary节点出现了大量慢查询。

孤儿文档的影响

一般情况下,发送方的孤儿文档会在chunk迁移后立即或延迟删除(根据waitForDelete参数来决决定),但如果chunk迁移发生了异常,以及异步删除孤儿文档有延迟,则有可能在发送方和接收方产生孤儿文档。如果用户一直是通过mongos进行分片集合的读写,那孤儿文档并不会对读写造成实际的影响。但如果用户通过直连分片集群*(当然了,这样的行为并不推荐)的shard进行读写,就会有可能发现同一个文档存在于多个shard上,出现读写不一致的现象**。

如何避免迁移

如下几点措施可以在一定程度上规避chunk自动迁移对业务的影响:

  1. 指定只在特定时间点可以进行chunk迁移(或者关闭balancer),避开业务高峰期

  2. 设置合理的分片建,保证chunk分布均匀,减少chunk迁移操作

  3. 预分片,减少chunk的迁移


http://www.ppmy.cn/devtools/53745.html

相关文章

宕机了, redis如何保证数据不丢?

前言 如果有人问你:"你会把 Redis 用在什么业务场景下?" 我想你大概率会说:"我会把它当作缓存使用,因为它把后端数据库中的数据存储在内存中,然后直接从内存中读取数据,响应速度会非常快。…

Unity中的AssetBundleManifest

在Unity中,AssetBundleManifest是一个重要的类,它包含了关于AssetBundles的元数据,如依赖关系、哈希值等。以下是对AssetBundleManifest类中常用属性和方法的清晰归纳: 常用属性 无直接公开属性:AssetBundleManifest…

QT-QPainter实现一个可切换的开关控件

1、效果 2、核心代码 #ifndef SWITCH_H #define SWITCH_H #include <QWidget> #include <QTimer>

spark学习总结第2天

系列文章目录 1- Spark词频统计案例加强-hdfs读写&#xff08;掌握&#xff09;2- Spark on Yarn 环境—验证案例&#xff08;操作&#xff09;3- spark-submit命令&#xff08;了解&#xff09;4- PySpark程序与Spark交互流程&#xff08;掌握&#xff09;5- 常见面试题&…

Mysql的索引

1.索引 Innodb 使用B树作为索引结构&#xff0c;索引跟数据存放在同一个文件中。表数据文件本身就是按照B树组织的一个索引结构&#xff0c;这颗树的叶子节点的data域保存了完整的数据记录&#xff0c;这个索引的key是数据表主键&#xff0c;InnoDB表数据文件本身就是主索引 …

手摸手系列之 - 什么是接口的幂等性以及 AOP+Redis 基于注解实现接口幂等性校验

接口的幂等性是指在分布式系统中&#xff0c;一个操作或者请求无论执行多少次&#xff0c;其结果都是相同的。换句话说&#xff0c;即使多次执行同一个操作&#xff0c;它也不会产生副作用&#xff0c;或者不会改变系统的状态。幂等性是设计 RESTful API 时的一个重要原则。 幂…

Zookeeper 集群节点故障剔除、切换、恢复原理

Zookeeper 集群节点故障剔除、切换、恢复原理 zookeeper 集群节点故障时,如何剔除节点,如果为领导节点如何处理,如何进行故障恢 复的,实现原理? 在 Zookeeper 集群中,当节点故障时,集群需要自动剔除故障节点并进行故障恢复,确保集群的高 可用性和一致性。具体来说,…

112、路径总和

给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径&#xff0c;这条路径上所有节点值相加等于目标和 targetSum 。如果存在&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 叶子节点 是指没有子节点…