Mongodb的分片机制是mongodb数据库的核心机制,也是其可用性高,扩展性好的原因,分片—sharding 的意思就是将数据库数据分散存贮到不同的服务器上,来缓解高并发访问,均衡负载。

举例来说一下,比如说一个collection有TB级别的数据,在传统方式下如果有两个线程要访问其中的数据,即使这个线程访问的数据是不同的,为保证同步需要排队等待,分片机制可以很好的解决这个问题,分片机制其实就是分布式的集群,比如现在有五台服务器作为集群,mongodb可以将一个collection的数据分割成5个片---chunk 分别存放到5个server并且mongodb还会记录下每一条数据的位置,这样一来当用户访问集合里面的文档时,mongodb可以根据请求条件来查找到对应数据所在的服务器然后返回数据,这样下来可以将多请求的负责分摊到各个服务器的分片上,大大提高数据库系统的吞吐量。

mongodb分片集群备份 mongodb中的分片是什么意思_数据库


可以看一下sharding的结构

最上面Router—路由器顾名思义就是请求转发的功能,具体就是mongodb里面的mongos可执行文件,mongos就是各种数据库请求的入口,mongos解析用户请求,然后将其转发至ConfigServer继续执行,为保证集群的高可用,在集群中一般不只一个mongos入口。

ConfigServer:所以configserver的作用就是为路由器提供分片线索,可以理解为各个不同分片的索引表一样,可以快速查到对应分片,然后就可以去访问shard服务器了。

Shard:数据库的真正的数据存放于shard上面,shard就表示集群中的某一个服务器的mognodb数据库实例。mongos可以统筹管理集群所有数据,mongod则是代表了本地数据库,这是两个不同的入口,如果通过mongod去访问数据库我们只能看到当前这个服务器的数据,mongos入口可以访问到5个服务器的全部数据
我们可以看到mongos路由不止一个,原因很简单,一个高可用分布式集群方案,必须保证服务时刻都可以正常高效运行,在这里在多个服务器配置同样的mongos路由,sh是为了fangzh是为了防止当前使用的路由出现问题而备用的。同样的configserver 同样需要完全相同副本分布在不同的服务器上备用,,shard也一样可以设置副本。

分片的原理:现在我们知道了为什么要把数据分散到不同rontde服务器上去,那么现在需要知道如何将一个collection的数据分片,也就是说分片的依据是什么?

mongodb分片集群备份 mongodb中的分片是什么意思_服务器_02


Shard key 分片依据,这个关键字只能去collcetion里面已有的字段,最常见的比如_id。 mongodb会根据我们选定的key来进行分片。

Mongodb为我们提供了两种分片的方式

• 范围分片(Range based sharding)

• hash分片(Hash based sharding)

mongodb分片集群备份 mongodb中的分片是什么意思_mongodb分片集群备份_03


从上图可以很容易理解这种不同的分片方式,Hash分片:对key进行hash映射,然后决定其存放于那一个分片上去,这种方式是很随机的。Range分片就是,顺序分片,根据关键字的顺序进行分片

对比一下两种分片方式各有利弊,我简单说一下:

Hash分片:可以选用任何字段作为hash key ,我试过不同的字段,比如有序的字段,String,还是自动生成的_id, 最后的分片的效果都不错,可以均匀的将数据分散到各个服务器上,但是最大的问题是,如果我们选定一个字段作为hash key 我们必须在分片之前在这个字段上建立hash 索引,没错,这里出现了hash索引,还记得我上一篇文章中说到的用hash方式做索引的利弊吗?

  1. 无法进行范围查找
  2. 可能导致索引表过于大,降低内存使用率。
    Mongodb可以建立hash索引当然有它的意义,只不过要看不同的业务场景,不同的业务需求。

Range分片:缺点很容易显现,,上图中我们选中x 字段作shard key x是有序的字段,我们为每一个server设定了映射范围,这样的问题就是容易产生超大chunk的问题,随着X的不断增长,新的数据将会全部投射到最后一个Server 上去,在数据量超大的情况下,数据容易在一个server上聚集,那么就失去了分片的意义,跟一台服务器没有什么区别了。还要注意Range 分片一样需要在分片之前在选定的key 上面建立对应的索引。我试过在mongodb自生成的_id 字段上使用Range 分片,最后的分片效果还是比较均匀的,但是没有hash 分片那么均匀。 还有一点,这样分片的成功也映证了我在索引那一片文章中讲的,系统会在PK上面自动建立主索引。注意我的数据量已经是数亿级别的。Range 分片在一定场景下也具有较好的分片能力。

Ok 在来说说具体的分片操作,这里面还有许多需要注意。以下我通过一个实例collection来讲解分片的过程。
1登陆mongos之后,首先切换到admin 数据库下
user admin
EnableSharding
//if this command work ,you can see the restore process script printed by the server, now you need to //make sure that every collection has been enablesharding, such as

enablesharding 首先激活citi这个collection 分片有效

db.runCommand( { enablesharding :"citi"});

set up the shard key for the collection

the choice of shard key is very important for the date shard

two choice you can try : hashed key or ranged key

here I have some advice for you:

usually we choose _id for the shard key. If you chose hashed shard you need to create a hash index in the field you choose and run this command before you restore data, it turns out that hash shard have a great performance in deal with the big data.

If you choose ranged shard, in case of data gather in one server make sure the _id is not ranged

选取shad key 这里选用_id 作为shard key range 分片方式

db.runCommand( { shardcollection : "pmch.citi",key : {_id: 1} } )

现在我们不断插入数据,看一下分片的情况

mongodb分片集群备份 mongodb中的分片是什么意思_数据库_04

mongodb分片集群备份 mongodb中的分片是什么意思_数据_05

mongodb分片集群备份 mongodb中的分片是什么意思_大数据_06