分片(sharding)是MongoDB用来将大型集合分割到不一样服务器(或者说一个集群)上所采用的方法。尽管分片起源于关系型数据库分区,但MongoDB分片彻底又是另外一回事。html
和MySQL分区方案相比,MongoDB的最大区别在于它几乎能自动完成全部事情,只要告诉MongoDB要分配数据,它就能自动维护数据在不一样服务器之间的均衡。算法
高数据量和吞吐量的数据库应用会对单机的性能形成较大压力,大的查询量会将单机的CPU耗尽,大的数据量对单机的存储压力较大,最终会耗尽系统的内存而将压力转移到磁盘IO上。数据库
为了解决这些问题,有两个基本的方法: 垂直扩展和水平扩展。后端
垂直扩展:增长更多的CPU和存储资源来扩展容量。服务器
水平扩展:将数据集分布在多个服务器上。水平扩展即分片。架构
分片为应对高吞吐量与大数据量提供了方法。使用分片减小了每一个分片须要处理的请求数,所以,经过水平扩展,集群能够提升本身的存储容量和吞吐量。举例来讲,当插入一条数据时,应用只须要访问存储这条数据的分片.性能
使用分片减小了每一个分片存储的数据。大数据
例如,若是数据库1tb的数据集,并有4个分片,而后每一个分片可能仅持有256 GB的数据。若是有40个分片,那么每一个切分可能只有25GB的数据。spa
1.对集群进行抽象,让集群“不可见”设计
MongoDB自带了一个叫作mongos的专有路由进程。mongos就是掌握统一路口的路由器,其会将客户端发来的请求准确无误的路由到集群中的一个或者一组服务器上,同时会把接收到的响应拼装起来发回到客户端。
2.保证集群老是可读写
MongoDB经过多种途径来确保集群的可用性和可靠性。将MongoDB的分片和复制功能结合使用,在确保数据分片到多台服务器的同时,也确保了每分数据都有相应的备份,这样就能够确保有服务器换掉时,其余的从库能够当即接替坏掉的部分继续工做。
3.使集群易于扩展
当系统须要更多的空间和资源的时候,MongoDB使咱们能够按需方便的扩充系统容量。
组件 |
说明 |
Config Server |
存储集群全部节点、分片数据路由信息。默认须要配置3个Config Server节点。 |
Mongos |
提供对外应用访问,全部操做均经过mongos执行。通常有多个mongos节点。数据迁移和数据自动平衡。 |
Mongod |
存储应用数据记录。通常有多个Mongod节点,达到数据分片目的。 |
分片集群的构造
(1)mongos :数据路由,和客户端打交道的模块。mongos自己没有任何数据,他也不知道该怎么处理这数据,去找config server
(2)config server:全部存、取数据的方式,全部shard节点的信息,分片功能的一些配置信息。能够理解为真实数据的元数据。
(3)shard:真正的数据存储位置,以chunk为单位存数据。
Mongos自己并不持久化数据,Sharded cluster全部的元数据都会存储到Config Server,而用户的数据会分散存储到各个shard。Mongos启动后,会从配置服务器加载元数据,开始提供服务,将用户的请求正确路由到对应的碎片。
Mongos的路由功能
当数据写入时,MongoDB Cluster根据分片键设计写入数据。
当外部语句发起数据查询时,MongoDB根据数据分布自动路由至指定节点返回数据。
在一个shard server内部,MongoDB仍是会把数据分为chunks,每一个chunk表明这个shard server内部一部分数据。chunk的产生,会有如下两个用途:
Splitting:当一个chunk的大小超过配置中的chunk size时,MongoDB的后台进程会把这个chunk切分红更小的chunk,从而避免chunk过大的状况
Balancing:在MongoDB中,balancer是一个后台进程,负责chunk的迁移,从而均衡各个shard server的负载,系统初始1个chunk,chunk size默认值64M,生产库上选择适合业务的chunk size是最好的。MongoDB会自动拆分和迁移chunks。
分片集群的数据分布(shard节点)
(1)使用chunk来存储数据
(2)进群搭建完成以后,默认开启一个chunk,大小是64M,
(3)存储需求超过64M,chunk会进行分裂,若是单位时间存储需求很大,设置更大的chunk
(4)chunk会被自动均衡迁移。
适合业务的chunksize是最好的。
chunk的分裂和迁移很是消耗IO资源;chunk分裂的时机:在插入和更新,读数据不会分裂。
chunksize的选择:
小的chunksize:数据均衡是迁移速度快,数据分布更均匀。数据分裂频繁,路由节点消耗更多资源。大的chunksize:数据分裂少。数据块移动集中消耗IO资源。一般100-200M
随着数据的增加,其中的数据大小超过了配置的chunk size,默认是64M,则这个chunk就会分裂成两个。数据的增加会让chunk分裂得愈来愈多。
这时候,各个shard 上的chunk数量就会不平衡。这时候,mongos中的一个组件balancer 就会执行自动平衡。把chunk从chunk数量最多的shard节点挪动到数量最少的节点。
chunkSize 对分裂及迁移的影响
MongoDB 默认的 chunkSize 为64MB,如无特殊需求,建议保持默认值;chunkSize 会直接影响到 chunk 分裂、迁移的行为。
chunkSize 越小,chunk 分裂及迁移越多,数据分布越均衡;反之,chunkSize 越大,chunk 分裂及迁移会更少,但可能致使数据分布不均。可能形成热点数据问题
chunkSize 过小,容易出现 jumbo chunk(即shardKey 的某个取值出现频率很高,这些文档只能放到一个 chunk 里,没法再分裂)而没法迁移;chunkSize 越大,则可能出现 chunk 内文档数太多(chunk 内文档数不能超过 250000 )而没法迁移。
chunk 自动分裂只会在数据写入时触发,因此若是将 chunkSize 改小,系统须要必定的时间来将 chunk 分裂到指定的大小。
chunk 只会分裂,不会合并,因此即便将 chunkSize 改大,现有的 chunk 数量不会减小,但 chunk 大小会随着写入不断增加,直到达到目标大小。
MongoDB中数据的分片是以集合为基本单位的,集合中的数据经过片键(Shard key)被分红多部分。其实片键就是在集合中选一个键,用该键的值做为数据拆分的依据。
因此一个好的片键对分片相当重要。片键必须是一个索引,经过sh.shardCollection加会自动建立索引(前提是此集合不存在的状况下)。一个自增的片键对写入和数据均匀分布就不是很好,由于自增的片键总会在一个分片上写入,后续达到某个阀值可能会写到别的分片。可是按照片键查询会很是高效。
随机片键对数据的均匀分布效果很好。注意尽可能避免在多个分片上进行查询。在全部分片上查询,mongos会对结果进行归并排序。
对集合进行分片时,你须要选择一个片键,片键是每条记录都必须包含的,且创建了索引的单个字段或复合字段,MongoDB按照片键将数据划分到不一样的数据块中,并将数据块均衡地分布到全部分片中。
为了按照片键划分数据块,MongoDB使用基于范围的分片方式或者 基于哈希的分片方式。
注意:
分片键是不可变。
分片键必须有索引。
分片键大小限制512bytes。
分片键用于路由查询。
MongoDB不接受已进行collection级分片的collection上插入无分片
键的文档(也不支持空值插入)
Sharded Cluster支持将单个集合的数据分散存储在多shard上,用户能够指定根据集合内文档的某个字段即shard key来进行范围分片(range sharding)。
对于基于范围的分片,MongoDB按照片键的范围把数据分红不一样部分。
假设有一个数字的片键:想象一个从负无穷到正无穷的直线,每个片键的值都在直线上画了一个点。MongoDB把这条直线划分为更短的不重叠的片断,并称之为数据块,每一个数据块包含了片键在必定范围内的数据。在使用片键作范围划分的系统中,拥有”相近”片键的文档极可能存储在同一个数据块中,所以也会存储在同一个分片中。
分片过程当中利用哈希索引做为分片的单个键,且哈希分片的片键只能使用一个字段,而基于哈希片键最大的好处就是保证数据在各个节点分布基本均匀。
对于基于哈希的分片,MongoDB计算一个字段的哈希值,并用这个哈希值来建立数据块。在使用基于哈希分片的系统中,拥有”相近”片键的文档极可能不会存储在同一个数据块中,所以数据的分离性更好一些。
Hash分片与范围分片互补,能将文档随机的分散到各个chunk,充分的扩展写能力,弥补了范围分片的不足,但不能高效的服务范围查询,全部的范围查询要分发到后端全部的Shard才能找出知足条件的文档。
1、递增的sharding key
数据文件挪动小。(优点)
由于数据文件递增,因此会把insert的写IO永久放在最后一片上,形成最后一片的写热点。同时,随着最后一片的数据量增大,将不断的发生迁移至以前的片上。
2、随机的sharding key
数据分布均匀,insert的写IO均匀分布在多个片上。(优点)
大量的随机IO,磁盘不堪重荷。
3、混合型key
大方向随机递增,小范围随机分布。
为了防止出现大量的chunk均衡迁移,可能形成的IO压力。咱们须要设置合理分片使用策略(片键的选择、分片算法(range、hash))
分片注意:
分片键是不可变、分片键必须有索引、分片键大小限制512bytes、分片键用于路由查询。
MongoDB不接受已进行collection级分片的collection上插入无分片键的文档(也不支持空值插入)
转自:https://www.cnblogs.com/clsn/p/8214345.html#auto_id_0