走进MongoDB(五)---- 分片

 本文从如下几个方面对MongoDB进行介绍mongodb

1、分片键组件shell

2、分片键数据库

3、哈希分片数组

4、范围分片缓存

5、区间安全

6、分片部署实例服务器

 

Sharding概述网络

是分片、或者分区的意思。分片是一个数据库架构,能够经过key 范围拆分数据而且把拆分后的数据分散的存储到两个或多个数据库实例。分片提供了水平扩展的功能。架构

MongoDB使用分片来支持超大数据集和高操做性能的部署要求。咱们可使用两种方法来支持数据量的大量增长和高性能操做要求:垂直扩展和水平扩展分布式

一、垂直扩展:

一般是增长单机容量,例如、使用性能更高的CPU、增长内存、增长硬盘存储空间。

二、水平扩展(mongodb使用sharding来支持水平扩展):

一般是将数据集进行分割,并将其分布到过个服务器上。经过增长额外的服务器来增长性能、容量的需求。由于每一个机器只负责处理全部工做量的一个子集,其中的每一台机器都不会要求特别高的容量和性能,这提供了比高配置的单机服务器更高的数据处理效率。面对部署集性能的扩展需求,只须要增长额外的服务器节点便可,这比使用高端硬件的单机服务器花费更低的成本。           

三、分片集群

Mongodb分片集群由如下组件构成:

Shard:每个分片都包含分片数据的一个子集。每个分片能够被部署为一个复本集。

Mongos:扮演一个查询路由的角色,在客户端程序和分片集群之间提供了一个路由接口。

Config servers:存储了集群的元数据和配置设置。Mongodb3.4开始,config servers必需要部署为一个复制集。

下图描述了分片集群中各组件之间的相互做用:

 

MongoDB把数据在表(collection)级别进行分区,将表数据分布到集群的各个分片上面。

四、分片键(shard key

为了在collection中分布documentsMongoDB使用shard key来分割collection。在目标collection中,分片键由每一个document中存在的不可变域(字段)组成。

当对一个collection进行分片的时候选择使用分片键。在分片以后,分片键是不可更改的。一个分片的collection只能有一个分片键。

对一个非空collection作分片,collection必需要设置一个由分片键开始的索引。对一个空的collection作分片,若是collection没有一个可用于分片键的合适的索引,mongodb会建立这个索引。

分片键的选择会影响分片集群的性能、效率和可扩展性。一个拥有高配置硬件环境和基础设施的集群可能会由于分片键的选择而出现较大的瓶颈。

五、Chunks

Mongodb会把分片数据分割成块。每个块。。。。。。

Mongodb在分片集群中使用分片集群平衡器在多个分片之间进行chunks的迁移。平衡器会尝试在集群中全部分片之间保持chunks的对等与平衡。

注:平衡器是在后台运行的程序,用于管理每个分片上chunks的数量。

六、分片的优点

/

MongoDB把读写工做量分布到集群中的多个分片上,容许每个分片处理一个集群操做的子集。读/写工做量均可以经过在集群中增长更多的分片来实现水平方向的扩展。

存储容量

集群中的每个分片包含集群数据总量的一个子集。当数据量增加的时候,额外的分片能够提高集群的数据存储容量。

高可用性

即便一个或者多个分片出现故障而不可用,分片集群仍然能够执行部分的读写操做。虽然,宕机期间故障分片上包含的数据子集是不可访问的,可是指向其它可用分片上的读写操做仍然能够成功执行。

Mongodb3.2开始,能够把config servers(配置服务器,存储分片集群的相关元数据及配置信息)部署为副本集。只要config servers的大部分副本可用,分片集群就能够继续进行读写操做的处理。MongoDB3.4开始,再也不支持SCCCSync Config Connection Config,仅仅支持CSRSConfig Server Replication Set)。

在生产环境中,每个单独的分片都应该被部署为一个副本集,以保证数据的冗余和可用性。

分片部署以前应该考虑的问题

分片集群基础设施须要和复杂性要求精心的计划、执行和维护。

在选择分片键的时候须要作一个仔细的考虑,由于这会直接影响集群的性能和效率。在分片设置以后就不能再改变分片键,你也不能取消已经分片的collection

分片具备一个确切的操做要求和限制。

若是查询不包含分片键或者复合分片键的前缀,mongos会执行一个广播操做,将在集群中的全部分片进行查询。这种分散性的查询操做会具备一个过长的运行时间。

七、分片collection和非分片collection

一个数据库能够同时拥有分片collection和非分片collection。分片集合被分割到集群中的多个分片上,非分片集合只存储在主分片节点。每个数据库都有本身的主分片。

 

八、链接一个分片集群

咱们必须先链接到mongos路由,在经过路由来和分片集群中的collection进行数据交互。客户端千万不要直接链接到一个单独的分片来执行读写操做。

 

咱们能够像链接到mongod同样链接到mongos。例如经过mongo shell或者mongodb driver

九、分片策略

MongoDB支持两种将数据分布到集群各个分片上的分片策略。

Hashed sharding(哈希分片)

哈希分片会根据分片键的值计算出一个哈希值。以后每个chunk(数据块)都被分配到基于分片键哈希值的一个范围。

当使用哈希索引解析查询时,mongodb会自动计算哈希值。

 

有一些分片键多是“靠近的”,他们的哈希值不太可能在同一个chunk。基于哈希的数据分配能够帮助更加均匀的分配数据,特别是在那些分片键单调改变的数据集中。

可是,哈希分配意味着,分片键上基于范围的查询指向一个单独分片的可能性会更小。致使集群进行普遍的广播操做()。

ranged sharding

范围分片是将数据分割成基于分片键值的一个范围。每个chunk被分配到基于分片键值的一个范围。

 

一些值是相近的“分片键”更可能驻留在相同的chunk上。这容许targeted operations(定向操做)由于mongos只会把操做路由到包含所需数据的分片。

十、分片集群中的区间(Zones in sharded clusters

在分片集群中,基于分片键(shard key)你能够为分片数据建立区域(一组documents)。在集群中,能够将一个区域和一个或多个分片相互关联。一个分片也能够和多个不相互冲突的zones相关联。在一个平衡的集群中,MongoDB仅仅会在与zone相关联的分片中,迁移被zone所包含的chunks

每个区域都会包含一个或多个分片键值区域。每个zone中所包含的范围老是包括它的下界、不包括它的上界。就是[ 1 , 10 ) :  1<=range<10

  

若是在zone中定义一个新的范围,必须使用包含在分片键里的域。若是使用混合分片键,那么这个范围必需要包含分片键的前缀。

在选择分片键的时候,要仔细考虑将来使用区域分片的可能性,由于在collection分片以后就不能够再更改分片键了。

Collations in sharding(分片中的字符串比对规则)

使用带有 collation:{locale:”simple”} 选项的shardCollection命令对一个具备默认比对规则的collection作分片。成功的分片又如下要求:

1.collection必须拥有一个前缀是分片键的索引。

2.索引必须具备{ locale : “simple” }比对规则。

若使用比对规则建立了collection,在分片collection以前要确保知足以前的条件。

 

1、分片集群组件

生产环境部署

在一个生产部署环境下,要确保数据的冗余和系统的高可用性。参考如下分片集群生产部署方案:

1 把配置服务器部署为3节点的复制集。

2 把每一个分片部署为3节点的复制集

3 部署一个或多个mongos路由

在可能的状况下,在一个适合做为灾难恢复的地点为每个复制集中部署一个节点。

分片集群要求至少要把数据分布到两个分片上。若是计划在将来须要的时候启动一个分片,可是在部署时并不须要此分片,这时候咱们能够部署一个单分片的分片集群。

能够为每个应用服务器部署一个mongos路由来确保每一个服务器均可以始终如一的访问分片集群。可选的,也能够在应用程序和mongos组中间部署一组mongos路由,而且使用一个代理或者负载平衡器。

开发环境部署

若是只是用于测试和开发,能够部署一个具备最小数量组件的分片集群。参考如下开发环境部署:

1 具备一个成员的配置服务器复制集

2 至少一个配置为单节点复制集的分片

3 一个mongos实例

 

分片

全部的分片在一块儿组成了集群的整个数据集。

用户、客户端、应用程序都应该只链接到一个单独的分片来执行本地管理和维护操做。

在单独分片上的查询只会返回数据的一个子集。要链接到mongos才能执行集群级别的查询(包括读、写操做)。

注:mongodb不能保证两个连续的chunks会驻留在同一个分片上。

1 主分片

分片集群上的每个数据库都有一个主分片,主分片持有了全部没有分片的collection。主分片和复制集中的主节点没有任何关系。

在建立一个新的数据库的时候,Mongos经过选择集群中具备最小数据量的那个分片做为主分片。Mongos使用由listDatabase 命令返回的totalSize域做为选择标准的一部分。

    

使用movePrimary命令来改变数据库的主分片。主分片的迁移过程可能会话费大量的时间才能完成,在处理完成以前都不该该访问collection中的数据。

当使用以前部署为复制集的服务器来做为分片配置为分片集群的时候,全部以前存在的数据都继续驻留在以前所在的位置。接下来建立的数据库可能驻留在集群上的任何一个分片上。

2 分片状态

mongo shell中使用sh.status()方法查看集群的信息报告。这个报告包含:哪一个分片是主分片、chunk(数据库)在全部分片上的分布。

分片集群安全

可使用内部认证来阻止没有经过认证的组件进入集群。

分片的本地用户

每一个分片都支持role-baseed access control,从而限制weigh未认证的用户访问分片数据(经过--auth选项来开启)。另外,也可使用Internal authentication(内部认证)来进行访问控制。

每一个分片都有其本身的本地分片用户。这些用户不能用于其它分片,也不能用于经过mongos来链接分片集群。

 

配置服务器(metadata

存储分片集群的元数据。元数据包含全部集群中数据和组件的状态和阻止形式,包含了每个分片上的chunks列表和定义在chunk里的范围。

Mongos缓存这些数据,而且用它们把读写操做路由到正确的分片上。当集群的元数据因为chunk分裂、新增分片而发生改变时,mondos也会更新想这些缓存。

配置服务器也会存储权限配置信息(如,基于角色的访问控制、内部认证)。

MongoDB也会使用配置服务器来管理分布式锁。

配置服务器复制集

MongoDB3.2开始,使用配置服务器复制集来提升一致性,由于MongoDB能够采起标准配置服务器复制集读写协议。另外,可使分片集群能够有3个以上的配置服务器,由于每个复制集均可以最多配置50个。要将配置服务器部署为复制集,必须使用WireTiger存储引擎。

限制:

1 不能有arbiters成员

2 不能有延时成员

3 必须构建索引

配置服务器上的读写操做

1

Admin数据库包含了与认证、受权相关的colletion,另外还有一些用于内部使用的system.* colletion

Config数据库中的collection包含了分片集群的元数据。当metadata变化时,mongodbconfig数据库写入数据。

在正常数据库操做和维护的过程当中,用户不要直接向config数据库直接写入数据。

当对config进行写入时,mongodb使用majority级别的写入确认(write concern

2

MongoDBadmin数据库读认证、受权数据和其它内部使用的数据。

当启动mongos或者metadata改变以后,MongoDB都会从config数据库读数据。分片也会从config服务器读取数据库元数据。

读数据的时候,会使用majority级别的read concern

配置服务器可用性

若是配置服务器丢失了主节点,而且没法成功选举一个新的主节点,集群元数据变成只读模式。这时,仍然能够对分片进行读写,可是不能够进行chunk的迁移、分割。若是全部的配置服务器都不能够,集群也是不可操做的。

Mongos缓存了配置服务器的元数据。全部配置服务器不可用的时候,若是mongos实例没有重启,仍然可使用集群,直到配置服务器回恢复使用。若是重启了mongosmongos将不能再对读写进行路由操做。

没有元数据,集群就是不可操做的。保证配置服务器的完整、可用、备份是很是重要的。与存储在集群分片上的其它数据相比,配置服务器数据量很小,并且具备相对更低的活动负载。

分片集群元数据

访问config数据库,须要链接mongos实例,而后使用:

Use config

一般状况下,不该该对config服务器中的数据进行直接的更改。Config数据库包含的collections:

changelog

chunks

collections

databases

lockpings

locks

mongos

settings

shards

Version

分片集群的安全性

使用内部认证来设置集群内的安全,防止未受权的集群组件访问集群。为了设置内部认证,必须启动集群中的每个mongod而且进行合适的安全设置。

路由(mongos

Mongos负责将查询和写操做路由到一个分片上。从应用程序看来mongos只提供了到分片集群的接口。

Mongos经过使用缓存的metadata来追踪哪些数据在哪个分片上。

最多见的作法是和应用程序服务器同一个系统上运行mongos实例,而在其它专用服务器或者分片上来维护mongos实例。

路由和结果处理

路由查询步骤

1 肯定必须接收查询的分片列表。

2 在全部目标分片上创建一个指针。

Mongos从每个目标分片中合并数据并返回document。像sorting等这样的查询修饰符,会在monogos实例检索结果以前,在一个分片上先执行查询过滤。

3.2版本开始,若是操做不要求在主分片上执行,在多个分片上运行聚合操做的时候,这些操做能够将结果路由到任何分片以合并结果,并避免重载该数据的主分片。

当查询包含分片键或者分片键的前缀,mongos会执行目标操做(将查询路由到集群的分片子集)。

对于不包含分片键的查询,mongos执行一个广播查询(到全部的分片检索数据)。可是,有些包含分片键的查询仍然会进行广播式查询,这取决于数据在集群中的分布和查询的选择性。

Mongos如何处理查询修饰符

1 sorting

若是使用sort()指针函数,则主分片会合并据结果并对其进行sort排序,最后经过mongos将数据返回给客户端。

2 limits

Mongoslimit发送给全部分片,在将数据返回给客户端以前,对结果集从新执行limit

3 skips

Mongos不会将skip参数发送给分片,而是从分片上检索未经跳过的结果,在结果所有组合后再跳过指定数量的documents

可是,当skiplimit一块儿使用的时候,mongos会将它们一块儿发送给分片,用以提升操做的执行效率。

 

确认链接到mongos实例

使用isMaster命令来肯定是否链接到mongoss。例如:

{

   "ismaster" : true,

   "msg" : "isdbgrid",

   "maxBsonObjectSize" : 16777216,

   "ok" : 1

}

若是链接到mongodd,返回结果里不会有isdbgrid这个字符串。

查询隔离

一般,分片环境中最快速的查询是:使用分片键和来自config server的元数据,将操做路由到一个单独的分片上。这些目标操做使用分片键来定位知足查询要求的documents所在的分片或者分片子集。

不包含分片键的查询必须查询全部分片,这是一种比较耗时的操做。

1 广播操做

Mongos对全部分片上的collection进行广播查询。除非其能够肯定哪个或几个分片储存了要查询的数据。

    

一旦mongos收到全部分片的相应,它会合并数据并返回结果documents。 广播操做的性能取决于集群的整体负载,以及网络延迟、单个分片负载和每一个分片返回的文档数量等变量。 只要有可能,都有利于有针对性地进行广播操做的操做。

多更新操做(updateMany() deleteMany())老是执行广播操做

尽量的使用能够出发目标操做的操做,而不是致使广播操做的操做。

2 目标操做

Mongos使用分片键值来定位chunk(它的范围包括分片键值)并把查询指向抱哈chunk的分片。

    

例如,分片键以下:

{ a: 1, b: 1, c: 1 }

Mongos会把包含完整分片键或者以下所示的分片键前缀的查询路由到一个指定的分片或者分片子集:

{ a: 1 }

{ a: 1, b: 1 }

全部的insertOne()会指向一个分片。insertMany()的每个document数组会指向一个单独的分片,可是不能保证数组中的全部documents都插入到一个分片中。

全部updateOne()replaceOne()deleteOne()操做必须包含分片键或者_id。不然MongoDB会返回错误。

Depending on the distribution of data in the cluster and the selectivity of the query, mongosmay still perform a broadcast operation to fulfill these queries.

3 索引使用

若是查询不包含分片键,mongos会将查询发送到全部分片。相应的,每个分片会使用分片键索引或者其它更有效的索引来完成查询。

若是查询包含由分片键和辅助索引索引的字段的多个子表达式,则能够将查询路由到特定的分片,而且分片将使用可以最有效地执行的索引。

分片集群安全性(RBAC和内部认证机制)

 

2、分片键

分片键肯定集合中documents的分布。分片键是存在于集合中每一个文档的索引字段或者索引的复合字段。

MongDB键值的范围对集合中的数据进行分区。 每一个范围定义了不重叠的分片键值范围,并与一个块相关联。

MongoDB尝试在群集中的碎片之间均匀分配块。 分片键与块分布的有效性有直接的关系。

 

一旦分割了一个集合,分片键和分片键值是不可变的;

您不能为该集合选择不一样的分片键。

您不能更新分片键字段的值。

分片键规格

要分割一个集合,必须为sh.shardCollection()方法指定目标集合和分片键:

Sh.shardCollection(namespance,key)

Namespace参数有字符串<database>.<collection>来指定。

Key参数由一个包含该字段的文档和该字段的索引遍历方向组成。

分片键索引

全部分片的集合必须具备一个支持分片键的索引;即索引能够是分片键上的索引或分片键是索引的前缀的复合索引。

若是集合为空,则sh.shardCollection()在分片键上建立索引,由于此索引尚不存在。

若是集合不为空,则必须先使用sh.shardCollection()建立索引。

若是删除分片键的最后一个有效索引,则经过在分片键上从新建立索引进行恢复。

1、惟一索引

对于分片集合,只有_id字段索引和分片键上的索引或分片键是前缀的复合索引能够是惟一的:

1 您不能在其余字段上分割具备惟一索引的集合。

2 您没法在分片集合的其余字段上建立惟一索引。

经过使用分片键上的惟一索引,MongoDB能够在分片键值上强制执行惟一性。 MongoDB在整个组合键上强制执行惟一性,而不是分片键的单个组件。 要在分片键值上强制执行惟一性,请将惟一参数做为true传递给sh.shardCollection()方法:

1 若是集合为空,这样的索引页不存在,sh.shardCollection()则在分片键上建立惟一的索引。

2 若是集合不为空,则必须先使用sh.shardCollection()建立索引。

虽然您可使用分片键是前缀的惟一组合索引,若是使用惟一参数,则该集合必须在分片键上具备惟一的索引。

您不能在哈希索引上指定惟一约束。

分片键的选择(影响chunk在集群上的分布)

理想的分片键容许MongoDB在整个集群中均匀分布文档。

 

1、集合大小

当分割不为空的集合时,分片键只能限制初始分片操做支持集合的最大值。

2、分片键基数

分片键的基数决定了平衡器产生chunks的最大值。这会下降或者消除集群的水平扩展效用。

一个惟一分片键值只能存在任意给定的一个chunk里。若是分片键基数为4,那么分片集群中不会超过4chunks,而且每个chunk存储了一个惟一分片键的值。这会把有效分片的数量限制为4个,而且扩展额外的分片是没有意义的。

下图,描述了将字段X设置为分片键。若是X基数很小,新数据的插入将以下方式分布到各个分片:

 

上例中的集群不可以水平扩展,由于全部写入操做都会被路由到当前分片的子集。

设置有很高基数的分片键也不能保证数据在分片集群中的均匀分布,可是能够更好的支持水平扩展。分片键的变化频率和比率也会有助于数据的分布。选择分片键的时候要把每一个因素都考虑进去。

若是数据模型要求分片键使用一个较小基数,那么考虑使用组合索引,使用一个具备相对较高基数的字段。

分片键频率

考虑一个表示分片键值范围的集合-分片键频率表明给定值在数据中出现的频率。若是大多数documents只包含这些值的一部分,那么存储这些document的块(chunks)将成为集群中的瓶颈。此外,随着这些块 的增加,它们会变得不可分割,由于它们不能再被进一步的分裂。这会下降或者消除集群的水平扩展效用。

下图,描述了将字段X设置为分片键。若是X值的子集以高频的方式发生,则插入数据的分布以下全部:

 

分片键的基数和变化率都有助于数据的分布。

若是必须使用分片键的高频值,考虑使用组合索引,并使用惟一索引或者低频值。

单调变化的分片键

单调递增或递减的分片键值更可能致使大部分数据都进入同一个分片。

这是由于,每一集群中都有一个上限为maxKey的块,maxkey比任何值都高。Minkey也相似。

若是,分片键值一直增长,全部新插入的数据都将路由到上限为maxkey的块。同理,一直递减的也是同样。

单调递增分片键值的数据插入,以下图:

 

若是必须使用单调变化的分片键值,考虑使用哈希分片。

 

3、哈希分片

介绍见概述

 

4、范围分片

介绍见概述 

 

5、区域/区间

区间概念见shard概述。

使用三个分片、两个区间的分片集群以下:

 

Behavior and Operations

一、Ranges

每一个区间包含一个或多个分片键值范围。区间形式:[ )

二、Balancer

在全部分片上均匀的分布数据。

对于每一个标记为迁移的chunk,平衡器会检查每一个可能目标分片的配置区间。若是chunk的范围落在某个区间内,平衡器会把chunk迁移到这个区间所在的分片。不包含在任何区间内的chunk可能被融合到集群中的任意一个分片。

在为分片集群配置区间,并分配到各个分片以后,集群会花费一些时间来融合受配置影响的数据。这依赖于集群中区块的分割和当前的数据分布。当平衡调整结束以后,全部包含在区间内的读写操做都会被路由到相应的分片上。

三、Shard key

当定义zone的新范围时,必须使用分片键中包含的字段。若是使用复合分片键,则范围必须包含分片键的前缀。

例如,给定一个分片键{a1b2c3},建立或更新一个区域来覆盖b的值须要包括a,将a做为前缀。建立或更新区域以覆盖c的值须要包括ab,将ab做为前缀。

您不能使用分片键中不存在的字段建立zone。例如,若是要根据地理位置对数据进行分区,则分片键至少须要一个包含地理数据的字段。

为集合选择分片键时,请考虑可能要用于配置区域的字段。分片后,将不能再更改分片键。

四、Hashed shard keys and zones

若使用哈希分片键,zone区间为a :  [ 1 , 5 ) 范围中1表明的是a的哈希值,而不是a的实际值。所以mongodb不能保证将a值在15之间的documents查询都路由到分片上的同一个区间。

5Shard Zone Boundaries

分片区域的范围始终包含下界、不包含上界。

 

6、分片部署实例

待完善 。。。。

相关文章
相关标签/搜索