天天看点

MongoDB · 特性分析 · Sharded cluster架构原理

当mongodb复制集遇到下面的业务场景时,你就需要考虑使用sharded cluster

存储容量需求超出单机磁盘容量

活跃的数据集超出单机内存容量,导致很多请求都要从磁盘读取数据,影响性能

写iops超出单个mongodb节点的写服务能力

MongoDB · 特性分析 · Sharded cluster架构原理

如上图所示,sharding cluster使得集合的数据可以分散到多个shard(复制集或者单个mongod节点)存储,使得mongodb具备了横向扩展(scale out)的能力,丰富了mongodb的应用场景。

sharded cluster由shard、mongos和config server 3个组件构成。

MongoDB · 特性分析 · Sharded cluster架构原理

mongos是sharded cluster的访问入口,强烈建议所有的管理操作、读写操作都通过mongos来完成,以保证cluster多个组件处于一致的状态。

mongos本身并不持久化数据,sharded cluster所有的元数据都会存储到config server(下一节详细介绍),而用户的数据则会分散存储到各个shard。mongos启动后,会从config server加载元数据,开始提供服务,将用户的请求正确路由到对应的shard。

sharded cluster支持将单个集合的数据分散存储在多个shard上,用户可以指定根据集合内文档的某个字段即shard key来分布数据,目前主要支持2种数据分布的策略,范围分片(range based sharding)或hash分片(hash based sharding)。

MongoDB · 特性分析 · Sharded cluster架构原理

如上图所示,集合根据x字段来分片,x的取值范围为[minkey, maxkey](x为整型,这里的minkey、maxkey为整型的最小值和最大值),将整个取值范围划分为多个chunk,每个chunk(通常配置为64mb)包含其中一小段的数据。

chunk1包含x的取值在[minkey, -75)的所有文档,而chunk2包含x取值在[-75, 25)之间的所有文档… 每个chunk的数据都存储在同一个shard上,每个shard可以存储很多个chunk,chunk存储在哪个shard的信息会存储在config server种,mongos也会根据各个shard上的chunk的数量来自动做负载均衡。

范围分片能很好的满足『范围查询』的需求,比如想查询x的值在[-30, 10]之间的所有文档,这时mongos直接能将请求路由到chunk2,就能查询出所有符合条件的文档。

范围分片的缺点在于,如果shardkey有明显递增(或者递减)趋势,则新插入的文档多会分布到同一个chunk,无法扩展写的能力,比如使用_id作为shard key,而mongodb自动生成的id高位是时间戳,是持续递增的。

hash分片是根据用户的shard key计算hash值(64bit整型),根据hash值按照『范围分片』的策略将文档分布到不同的chunk。

MongoDB · 特性分析 · Sharded cluster架构原理

hash分片与范围分片互补,能将文档随机的分散到各个chunk,充分的扩展写能力,弥补了范围分片的不足,但不能高效的服务范围查询,所有的范围查询要分发到后端所有的shard才能找出满足条件的文档。

选择shard key时,要根据业务的需求及『范围分片』和『hash分片』2种方式的优缺点合理选择,同时还要注意shard key的取值一定要足够多,否则会出现单个jumbo chunk,即单个chunk非常大并且无法分裂(split);比如某集合存储用户的信息,按照age字段分片,而age的取值非常有限,必定会导致单个chunk非常大。

mongos作为sharded cluster的访问入口,所有的请求都由mongos来路由、分发、合并,这些动作对客户端driver透明,用户连接mongos就像连接mongod一样使用。

mongos会根据请求类型及shard key将请求路由到对应的shard

查询请求不包含shard key,则必须将查询分发到所有的shard,然后合并查询结果返回给客户端

查询请求包含shard key,则直接根据shard key计算出需要查询的chunk,向对应的shard发送查询请求

写操作必须包含shard key,mongos根据shard key算出文档应该存储到哪个chunk,然后将写请求发送到chunk所在的shard。

更新、删除请求的查询条件必须包含shard key或者_id,如果是包含shard key,则直接路由到指定的chunk,如果只包含_id,则需将请求发送至所有的shard。

除增删改查外的其他命令请求处理方式都不尽相同,有各自的处理逻辑,比如listdatabases命令,会向每个shard及config server转发listdatabases请求,然后将结果进行合并。

config server存储sharded cluster的所有元数据,所有的元数据都存储在config数据库,3.2版本后,config server可部署为一个独立的复制集,极大的方便了sharded cluster的运维管理。

config.shards集合存储各个shard的信息,可通过addshard、removeshard命令来动态的从sharded cluster里增加或移除shard。如下所示,cluster目前拥有2个shard,均为复制集。

如下命令,针对shtest数据里的hello集合开启分片,使用x字段作为shard key来进行范围分片。

集合分片开启后,默认会创建一个新的chunk,shard key取值[minkey, maxkey]内的文档(即所有的文档)都会存储到这个chunk。当使用hash分片策略时,可以预先创建多个chunk,以减少chunk的迁移。

当chunk里写入的数据量增加到一定阈值时,会触发chunk分裂,将一个chunk的范围分裂为多个chunk,当各个shard上chunk数量不均衡时,会触发chunk在shard间的迁移。如下所示,shtest.coll的一个chunk,在写入数据后分裂成3个chunk。

config.settings集合里主要存储sharded cluster的配置信息,比如chunk size,是否开启balancer等

config.changelog主要存储sharding cluster里的所有变更操作,比如balancer迁移chunk的动作就会记录到changelog里;

config.mongos存储当前集群所有mongos的信息;

config.locks存储锁相关的信息,对某个集合进行操作时,比如movechunk,需要先获取锁,避免多个mongos同时迁移同一个集合的chunk。

<a href="https://yq.aliyun.com/articles/64?spm=0.0.0.0.9jrpm8" target="_blank">mongodb复制集架构原理</a>

<a href="https://docs.mongodb.org/manual/core/sharding-introduction/" target="_blank">mongodb sharding简介</a>

<a href="https://docs.mongodb.org/manual/core/sharded-cluster-shards/" target="_blank">primary shard</a>

<a href="https://docs.mongodb.org/manual/reference/method/sh.enablesharding/" target="_blank">enablesharding命令</a>

<a href="https://docs.mongodb.org/manual/reference/command/moveprimary/" target="_blank">moveprimary命令</a>

<a href="https://docs.mongodb.org/manual/reference/command/shardcollection/" target="_blank">shardcollection</a>

<a href="https://docs.mongodb.org/manual/reference/command/nav-sharding/" target="_blank">sharding的管理操作</a>

<a href="https://docs.mongodb.org/manual/tutorial/deploy-shard-cluster/" target="_blank">部署sharded cluster</a>