什么是分片

分片(sharding)是MongoDB用来将大型集合水平分割到不同服务器(或者复制集)上所采用的方法。 不需要功能强大的大型计算机就可以存储更多的数据,处理更大的负载。

为什么要分片

  1. 存储容量需求超出单机磁盘容量。
  2. 活跃的数据集超出单机内存容量,导致很多请求都要从磁盘读取数据,影响性能。
  3. IOPS超出单个MongoDB节点的服务能力,随着数据的增长,单机实例的瓶颈会越来越明显。

4 .副本集具有节点数量限制。
垂直扩展:增加更多的CPU和存储资源来扩展容量。
水平扩展:将数据集分布在多个服务器上。水平扩展即分片。

分片的工作原理

image.png

分片集群由以下3个服务组成: Shards Server: 每个shard由一个或多个mongod进程组成,用于存储数据。 Router Server: 数据库集群的请求入口,所有请求都通过Router(mongos)进行协调,不需要在应用程 序添加一个路由选择器,Router(mongos)就是一个请求分发中心它负责把应用程序的请求转发到对应的 Shard服务器上。 Config Server: 配置服务器。存储所有数据库元信息(路由、分片)的配置。

片键(shard key)

为了在数据集合中分配文档,MongoDB使用分片主键分割集合。

区块(chunk)

在一个shard server内部,MongoDB还是会把数据分为chunks,每个chunk代表这个shardserver内部一部分数据。MongoDB分割分片数据到区块,每一个区块包含基于分片主键的左闭右开的区间范围。

分片策略

范围分片(Range based sharding)

image.png
范围分片是基于分片主键的值切分数据,每一个区块将会分配到一个范围。
范围分片适合满足在一定范围内的查找,例如查找X的值在[20,30)之间的数据,mongo 路由根据Confifig server中存储的元数据,可以直接定位到指定的shard的Chunk中。
缺点: 如果shard key有明显递增(或者递减)趋势,则新插入的文档多会分布到同一个chunk,无法扩展写的能力。

hash分片(Hash based sharding)

image.png
Hash分片是计算一个分片主键的hash值,每一个区块将分配一个范围的hash值。
Hash分片与范围分片互补,能将文档随机的分散到各个chunk,充分的扩展写能力,弥补了范围分片的不足,缺点是不能高效的服务范围查询,所有的范围查询要分发到后端所有的Shard才能找出满足条件的文档。

组合片键 A + B(散列思想 不能是直接hash)

数据库中没有比较合适的片键供选择,或者是打算使用的片键基数太小(即变化少如星期只有7天可变化),可以选另一个字段使用组合片键,甚至可以添加冗余字段来组合。一般是粗粒度+细粒度进行组合。

合理的选择shard key

无非从两个方面考虑,数据的查询和写入,最好的效果就是数据查询时能命中更少的分片,数据写入时能够随机的写入每个分片,关键在于如何权衡性能和负载。