mongodb分片原理

分片介绍

分片是使用多个机器存储数据的方法,MongoDB使用分片以支持巨大的数据存储量与对数据操作.

分片的目的

高数据量和吞吐量的数据库应用会对单机的性能造成较大压力,大的查询量会将单机的CPU耗尽,大的数据量对单机的存储压力较大,最终会耗尽系统的内存而将压力转移到磁盘IO上.

为了解决这些问题,有两个基本的方法: 纵向扩展 和 分片 .

 

 sharded-collection.png

分片为应对高吞吐量与大数据量提供了方法.

  • 使用分片减少了每个分片需要处理的请求数,因此,通过 水平扩展 ,集群可以提高自己的存储容量和吞吐量.

    举例来说,当插入一条数据时,应用只需要访问存储这条数据的分片.

  • 使用分片减少了每个分片存储的数据.

    举例来说,如果一个数据库有1TB数据,并有4个分片,则每个分片只需要存储256GB数据,如果数据库有40个分片,则每个分片只需要存储25GB数据.

 

MongoDB的分片

MongoDB通过配置 集群 支持分片.

Diagram of a sample sharded cluster for production purposes.  Contains exactly 3 config servers, 2 or more ``mongos`` query routers, and at least 2 shards. The shards are replica sets.

Diagram of a sample sharded cluster for production purposes. Contains exactly 3 config servers, 2 or more mongos query routers, and at least 2 shards. The shards are replica sets.

集群拥有以下组件: 分片分发路由,:term:配置服务器 <config server>.

Shards store the data. To provide high availability and data consistency, in a production sharded cluster, each shard is a replica set [1]. For more information on replica sets, see Replica Sets.

Query Routers, or mongos instances, interface with client applications and direct operations to the appropriate shard or shards. The query router processes and targets operations to shards and then returns results to the clients. A sharded cluster can contain more than one query router to divide the client request load. A client sends requests to one query router. Most sharded cluster have many query routers.

Config servers store the cluster’s metadata. This data contains a mapping of the cluster’s data set to the shards. The query router uses this metadata to target operations to specific shards. Production sharded clusters have exactly 3 config servers.

[1]

在测试与开发环境下,每个 分片 可以是单独的 mongod 而不用必须是复制集.在生产环境中 必须 部署3台配置服务器.

数据分区

MongoDB中数据的分片是以集合为基本单位的,集合中的数据通过 片键 被分成多部分.

片键

对集合进行分片时,你需要选择一个 片键 , shard key 是每条记录都必须包含的,且建立了索引的单个字段或复合字段,MongoDB按照片键将数据划分到不同的 数据块 中,并将 数据块 均衡地分布到所有分片中.为了按照片键划分数据块,MongoDB使用 基于范围的分片方式 或者 基于哈希的分片方式 ,参见 片键 获得更多信息.

以范围为基础的分片

对于 基于范围的分片 ,MongoDB按照片键的范围把数据分成不同部分.假设有一个数字的片键:想象一个从负无穷到正无穷的直线,每一个片键的值都在直线上画了一个点.MongoDB把这条直线划分为更短的不重叠的片段,并称之为 数据块 ,每个数据块包含了片键在一定范围内的数据.

在使用片键做范围划分的系统中,拥有”相近”片键的文档很可能存储在同一个数据块中,因此也会存储在同一个分片中.

Diagram of the shard key value space segmented into smaller ranges or chunks.

Diagram of the shard key value space segmented into smaller ranges or chunks.

基于哈希的分片

对于 基于哈希的分片 ,MongoDB计算一个字段的哈希值,并用这个哈希值来创建数据块.

在使用基于哈希分片的系统中,拥有”相近”片键的文档 很可能不会 存储在同一个数据块中,因此数据的分离性更好一些.

Diagram of the hashed based segmentation.

Diagram of the hashed based segmentation.

基于范围的分片方式与基于哈希的分片方式性能对比

基于范围的分片方式提供了更高效的范围查询,给定一个片键的范围,分发路由可以很简单地确定哪个数据块存储了请求需要的数据,并将请求转发到相应的分片中.

不过,基于范围的分片会导致数据在不同分片上的不均衡,有时候,带来的消极作用会大于查询性能的积极作用.比如,如果片键所在的字段是线性增长的,一定时间内的所有请求都会落到某个固定的数据块中,最终导致分布在同一个分片中.在这种情况下,一小部分分片承载了集群大部分的数据,系统并不能很好地进行扩展.

与此相比,基于哈希的分片方式以范围查询性能的损失为代价,保证了集群中数据的均衡.哈希值的随机性使数据随机分布在每个数据块中,因此也随机分布在不同分片中.但是也正由于随机性,一个范围查询很难确定应该请求哪些分片,通常为了返回需要的结果,需要请求所有分片.

使用标记自定义集群中数据的分布

MongoDB允许管理员使用 标记 直接决定集群的均衡策略.管理员使用标记与片键的范围做绑定,并将标记与分片直接绑定,之后,均衡器会将满足标记的数据直接分发到与之绑定的分片上,并且确保之后满足标记的数据一直存储在相应的分片上.

标记是控制均衡器行为和数据块分布的首要条件,一般来讲,在拥有多个数据中心时,才会使用标记自定义集群中数据块的分布,以提高不同地域之间数据访问的效率.

参见 受标记作用的分片 获得更多信息.

数据均衡的维护

新数据的加入或者新分片的加入可能会导致集群中数据的不均衡,即表现为有些分片保存的数据块数目显著地大于其他分片保存的数据块数.

MongoBD使用两个过程维护集群中数据的均衡:分裂和均衡器.

分裂

分裂是防止某个数据块过大而进行的一个后台任务.当一个数据块的大小超过 :ref:`设定的数据块大小 <sharding-chunk-size>`时,MongoDB会将其一分为二,插入与更新触发分裂过程.分裂改变了元信息,但是效率很高.进行分裂时,MongoDB 不会 迁移任何数据,对集群性能也没有影响.

Diagram of a shard with a chunk that exceeds the default chunk size of 64 MB and triggers a split of the chunk into two chunks.

Diagram of a shard with a chunk that exceeds the default chunk size of 64 MB and triggers a split of the chunk into two chunks.

均衡

The balancer is a background process that manages chunk migrations. The balancer runs in all of the query routers in a cluster.

当集群中数据的不均衡发生时,均衡器会将数据块从数据块数目最多的分片迁移到数据块最少的分片上,举例来讲:如果集合 users 在 分片1 上有100个数据块,在 分片2 上有50个数据块,均衡器会将数据块从 分片1 一直向 分片2 迁移,一直到数据均衡为止.

分片管理在后台管理从 源分片 到 目标分片 的 数据块迁移 ,在迁移过程中, 目标分片 首先会接收源分片在迁移数据块上的所有数据,之后,目标分片应用在上一迁移步骤之间发生在源分片上的迁移数据块的更改,最后,存储在 配置服务器 上的元信息被更新.

如果迁移中发生错误,源分片上的数据不会被修改,迁移会停止.在迁移成功 结束 之后MongoDB才会在源分片上将数据删除.

Diagram of a collection distributed across three shards. For this collection, the difference in the number of chunks between the shards reaches the *migration thresholds* (in this case, 2) and triggers migration.

Diagram of a collection distributed across three shards. For this collection, the difference in the number of chunks between the shards reaches the migration thresholds (in this case, 2) and triggers migration.

在集群中增加或者删除分片

在集群中增加分片时,由于新的分片上并没有数据块,会造成数据的不均衡.此时MongoDB会立即开始向新分片迁移数据,集群达到数据均衡的状态需要花费一些时间.

当删除一个分片时,均衡器需要将被删除的分片上的数据全部迁移到其他分片上,在全部迁移结束且元信息更新完毕之后,你可以安全地将这个分片移除.

 

 

集群组件

Sharded clusters implement sharding. A sharded cluster consists of the following components:

  • 分片

  • 分片是存储了一个集合部分数据的MongoDB实例,每个分片是单独的 mongod 或者是 replica set .在生产环境中,所有的分片都应该是复制集.参见 分片 获得更多信息.

  • 配置服务器

  • 每个:ref:配置服务器 <sharding-config-server>`都是存储了集群元信息的 :program:`mongod.元信息存储了 数据块对分片的映射,参见 配置服务器.获得更多信息.

  • 分发路由

  • 每个路由都是 mongos ,它将读写请求分发到分片中.应用并不直接访问分片.Diagram of a sharded cluster.

Diagram of a sharded cluster.

MongoDB中分片的基本单位是集合,对每个开启了分片的集合,都可以设置一个 shard key .

Further Reading

  • 分片

  • A shard is a mongod instance that holds a part of the sharded collection’s data.

  • 配置服务器

  • Config servers hold the metadata about the cluster, such as the shard location of the data.

 

分片

分片是存储了集群一部分数据的 mongod 或者 replica set.所有分片存储了集群的全部数据.

通常来讲,每个分片都是一个复制集.复制集为每个分片的数据提供了冗余和高可靠性.

重要

MongoDB以 每个集合 为单位使用分片,你 必须 通过 mongos 访问开启了分片的集合,如果直接连接到某个分片,你只能看到集合的部分数据.每个分片上的数据并没有特定的顺序.MongoDB并不保证两个连续的数据块会分布在同一个分片上.

主分片

每个数据库都有一个”主分片” [1] 用来存储这个数据库中所有未开启分片的集合的数据.

Diagram of a primary shard. A primary shard contains non-sharded collections as well as chunks of documents from sharded collections. Shard A is the primary shard.

Diagram of a primary shard. A primary shard contains non-sharded collections as well as chunks of documents from sharded collections. Shard A is the primary shard.

使用 movePrimary 来改变数据库的主分片.

警告

The movePrimary command can be expensive because it copies all non-sharded data to the new shard. During this time, this data will be unavailable for other operations.

当你用之前是复制集的分片创建一个新的 sharded cluster 时,所有原来在复制集中的数据都会依然保存在这个复制集中,随后创建的数据库有可能存储在任意一个分片中.

[1]

“主分片”与 复制集 中的 primary 没有任何关系.

集群状态

在 mongo 终端中使用 sh.status() 获得集群状态的概览.这个概览包括了每个数据库的主分片以及分片之间 chunk 的分布

 

 

配置服务器

配置服务器是保存集群中 元信息 的特殊 mongod . 配置服务器使用两段提交的方法来保证即时一致性和可靠性.配置服务器 并不 以复制集的方式运行,所有的配置服务器都可用是部署一个集群或者修改集群元信息的前提.

生产环境中的集群有 精确的三个 配置服务器,在测试环境中,你可以只使用一个配置服务器来部署一个集群,但在生产环境中,为确保冗余与安全,应该总是使用三个.

警告

如果你的集群只有一个配置服务器,那这个配置服务是单点服务,如果这个配置服务器不能被访问,集群将不可服务,如果你不能将配置服务器的数据恢复,整个集群将不能再被使用.

在生产环境中 一定 要使用三台配置服务器

每个集群都应该有自己的配置服务器,不要在不同的集群中使用同一个配置服务器.

小技巧

使用CNAMEs标记你的配置服务器,这样可以在重命名或者改变配置服务器的顺序时不需要停机.

Config 数据库

配置服务器在 config 数据库 中存储了集群的元信息, mongos 缓存了这个数据库用来做读写的路由分发.

配置服务器上的读写操作

MongoDB只有在以下情况下才会向配置服务器写数据:

  • 对存在的数据块进行分裂,

  • 在分片间进行数据块的迁移,

MongoDB在以下情况下从配置服务器读取数据:

  • 新的 mongos 第一次启动时,或者重启时.

  • 数据块迁移后, mongos 会更新自己的集群元信息.

MongoDB使用配置服务器管理分布锁.

配置服务器可用性

如果集群中一个或者两个配置服务器不可用,集群的元信息将变为 可读 ,你还可以从分片中读写信息,但是数据块的迁移以及数据块的分裂在所有配置服务器都恢复可用之前不能够进行.

如果所有的三个配置服务器都不可用,在重启 mongos 之前集群依然可用. 但是一旦试图重启 mongos ,集群将不能提供任何服务.

没有集群的元信息,集群将不能正常工作,因此,要 时刻 保持配置服务器的可用和完整.因此,配置服务器的备份是很重要的.与分片中的数据相比,配置服务器存储的信息要小很多.这意味着配置服务器有相对较小的请求负载,而且对于集群的正常运行,并不需要所有配置服务器任意时刻都可用,所以,备份配置服务器是一件容易的事情.

如果集群使用的配置服务器变换了ip或者域名,你需要重启 所有 的 mongod 和 mongos .可以在集群部署时使用CNAMEs避免重启.

 

 

分片间的数据块迁移

分片间数据块的迁移是 均衡器 过程的一部分.

Diagram of a collection distributed across three shards. For this collection, the difference in the number of chunks between the shards reaches the *migration thresholds* (in this case, 2) and triggers migration.

Diagram of a collection distributed across three shards. For this collection, the difference in the number of chunks between the shards reaches the migration thresholds (in this case, 2) and triggers migration.

数据块迁移

为了维持 sharded cluster 中的数据均衡,MongoDB在分片间迁移数据,迁移可以是以下两种情况:

  • 手工进行.只有在极少数情况下才需要手动迁移数据块,比如在批量写入时进行数据分发.参见 手动迁移数据块 获得更多细节.

  • 自动进行.在集群中发生数据不均衡时, 均衡器 会自动在分片间进行数据迁移,参见 迁移阈值 以获得更多细节.

所有的数据迁移都包含以下过程:

  1. 均衡器将 moveChunk 命令发送到源分片上.

  2. 源分片使用内部命令 moveChunk 开始迁移数据过程,在迁移过程中,对迁移数据块的请求都被分发到源分片.

  3. 目标分片开始向源分片请求要迁移的数据块的数据,接收并保存.

  4. 在所有文档都接收完成后,目标分片开始同步过程,以保证迁移期间对迁移数据块的所有更改都可以同步过来.

  5. 当同步结束之后,目标分片通知 config database 并使用数据块的新位置更新集群的元信息.

  6. 在目标分片更新完成元信息之后,一旦源分片的数据块中没有打开的游标,源分片会删除这部分重复的数据.

    在 2.4 版更改: 如果源分片需要继续进行数据迁移,迁移过程可以立刻开始,而不需要等待删除数据完成,参见 数据块迁移排队.

数据迁移可以保证一致性,并且尽力保证数据块在迁移过程中的可用性.

数据块迁移排队

在 2.4 版更改.

如果需要从一个分片迁移多个数据块到其他分片,每次只能迁移一个.不过,下一次迁移会在上一次迁移开始删除数据时就开始.参见 数据块迁移 获得更多数据块迁移和删除阶段的信息.

数据块迁移排队的行为可以在发生严重数据不均衡的情况下,分片更快的进行数据迁移,比如在一开始写入数据且集群没有进行预分配数据块时,或者新增一个分片时.

这种行为也同样影响 moveChunk 命令,这个命令也会因此变得更快.

在某些情况下,删除数据阶段会持续很久.如果多个删除数据任务在排队但是没有完成,分片中复制集主节点的异常关闭会导致孤儿文档的产生.

数据块迁移与复制集

默认情况下,每条被迁移的文档都必须被同步打牌至少一个从节点上之后,下一条文档才能开始迁移.

将 _secondaryThrottle 参数设置为false可以改变这种行为,使迁移不用等待数据同步到从节点便可以继续进行.参见 改变数据块迁移时的复制集行为(Secondary Throttle) 获取如何更新 _secondaryThrottle 的信息.

与 secondaryThrottle 设置无关,迁移中的一些阶段遵循一下的复制集策略:

  • 在更新配置服务器的集群元信息时,MongoDB会短暂地暂停掉源分片的所有写入,更新完成之后恢复.在将数据块迁移提交到配置服务器之前与之后,都需要确保所有写入被复制集的大多数节点所同步.

  • 当迁移即将结束并进去数据清理阶段时,所有的写入都必须同步到复制集的大多数节点之后,之后的数据清理(来自其他的数据迁移)或者新的迁移才可以进行.

在 2.4 版更改: 在之前的版本里,均衡器并不会等待数据在复制集中被同步到从节点

 

集群中chunk的分裂

当数据块的大小增长到超过 :ref:` 设定的数据块大小 <sharding-chunk-size>` 时,一个 mongos 会试图将这个数据块分裂成两个,分裂可能会导致不同分片之间数据块数量的不均衡.在这种情况下, mongos 会开始一次分片间的迁移使数据块重新均衡,参见 开启分片集合的均衡 获取更多分片间数据块均衡的细节.

Diagram of a shard with a chunk that exceeds the default chunk size of 64 MB and triggers a split of the chunk into two chunks.

Diagram of a shard with a chunk that exceeds the default chunk size of 64 MB and triggers a split of the chunk into two chunks.

数据块大小

MongoDB中默认的 chunk 大小是64M,你可以 调整数据块的大小,但要注意到这有可能会集群造成性能影响.

  1. 数据块大小较小时可以使得分片间的数据更均衡,但是是以频繁的迁移为代价的,会对 mongos 造成压力.

  2. 数据块大小较大时会使得均衡较少,这从网络传输  mongos 的角度来说更高效,但是,这种高效是通过数据不均衡的加重为代价的.

在很多情况下,以分片间数据略微的不均衡来防止频繁的迁移或者无效的迁移,是合理的.

限制

修改数据块大小影响数据块的分裂,但他的影响受到其他的一些限制.

  • 自动分裂只在数据插入与更新时发生,因此如果你减小了数据块的大小,需要花费一些时间使所有数据块分裂成新大大小.

  • 分裂不能被回滚,如果你增加了数据块大小,现有的数据块只有通过插入与更新才能逐渐达到新的设定值.

注解

数据块的范围包含了范围中的最小值,不包含最大值.










本文转自 zouqingyun 51CTO博客,原文链接:http://blog.51cto.com/zouqingyun/1681395,如需转载请自行联系原作者
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值