为什么需要Sharded cluster?

MongoDB目前3大核心优势:『灵活模式』+ 『高可用性』 + 『可扩展性』,通过json文档来实现灵活模式,通过复制集来保证高可用,通过Sharded cluster来保证可扩展性。

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

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

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

  • 写IOPS超出单个MongoDB节点的写服务能力

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

Sharded cluster架构

Sharded cluster由Shard、Mongos和Config server 3个组件构成。

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)。

范围分片

如上图所示,集合根据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分片

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

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

合理的选择shard key

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

Mongos

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

config database

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

config.shards

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

mongos> db.addShard("mongo-9003/10.1.72.135:9003,10.1.72.136:9003,10.1.72.137:9003")
mongos> db.addShard("mongo-9003/10.1.72.135:9003,10.1.72.136:9003,10.1.72.137:9003")
mongos> db.shards.find()
{ "_id" : "mongo-9003", "host" : "mongo-9003/10.1.72.135:9003,10.1.72.136:9003,10.1.72.137:9003" }
{ "_id" : "mongo-9004", "host" : "mongo-9004/10.1.72.135:9004,10.1.72.136:9004,10.1.72.137:9004" }

config.databases

config.databases集合存储所有数据库的信息,包括DB是否开启分片,primary shard信息,对于数据库内没有开启分片的集合,所有的数据都会存储在数据库的primary shard上。

如下所示,shtest数据库是开启分片的(通过enableSharding命令),primary shard为mongo-9003; 而test数据库没有开启分片,primary shard为mongo-9003。

mongos> use configuse config
switched to db config
mongos>  db.databases.find() db.databases.find()
{ "_id" : "admin", "partitioned" : false, "primary" : "config" }
{ "_id" : "testdb", "partitioned" : true, "primary" : "shard1" }
{ "_id" : "test", "partitioned" : false, "primary" : "shard1" }
{ "_id" : "dbtest", "partitioned" : false, "primary" : "shard1" }
{ "_id" : "noshare", "partitioned" : false, "primary" : "shard3" }
{ "_id" : "noshare2", "partitioned" : true, "primary" : "shard3" }
mongos>

Sharded cluster在数据库创建时,为用户选择当前存储数据量最小的shard作为数据库的primary shard,用户也可调用movePrimary命令来改变primary shard以实现负载均衡,一旦primary shard发生改变,mongos会自动将数据迁移到的新的primary shard上

config.colletions

数据分片是针对集合维度的,某个数据库开启分片功能后,如果需要让其中的集合分片存储,则需调用shardCollection命令来针对集合开启分片。

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

mongos> sh.shardCollection("shtest.coll", {x: 1})
{ "collectionsharded" : "shtest.coll", "ok" : 1 }
mongos> db.collections.find()
{ "_id" : "shtest.coll", "lastmodEpoch" : ObjectId("57175142c34046c3b556d302"), "lastmod" : ISODate("1970-02-19T17:02:47.296Z"), "dropped" : false, "key" : { "x" : 1 }, "unique" : false }

config.chunks

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

mongos> db.chunks.find({ns: "shtest.coll"})
{ "_id" : "shtest.coll-x_MinKey", "ns" : "shtest.coll", "min" : { "x" : { "$minKey" : 1 } }, "max" : { "x" : { "$maxKey" : 1 } }, "shard" : "mongo-9003", "lastmod" : Timestamp(1, 0), "lastmodEpoch" : ObjectId("5717530fc34046c3b556d361") }

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

ongos> use shtest
mongos> for (var i = 0; i < 10000; i++) { db.coll.insert( {x: i} ); }
mongos> use configmongos> db.chunks.find({ns: "shtest.coll"}){ "_id" : "shtest.coll-x_MinKey", "lastmod" : Timestamp(5, 1), "lastmodEpoch" : ObjectId("5703a512a7f97d0799416e2b"), "ns" : "shtest.coll", "min" : { "x" : { "$minKey" : 1 } }, "max" : { "x" : 1 }, "shard" : "mongo-9003" }{ "_id" : "shtest.coll-x_1.0", "lastmod" : Timestamp(4, 0), "lastmodEpoch" : ObjectId("5703a512a7f97d0799416e2b"), "ns" : "shtest.coll", "min" : { "x" : 1 }, "max" : { "x" : 31 }, "shard" : "mongo-9003" }{ "_id" : "shtest.coll-x_31.0", "lastmod" : Timestamp(5, 0), "lastmodEpoch" : ObjectId("5703a512a7f97d0799416e2b"), "ns" : "shtest.coll", "min" : { "x" : 31 }, "max" : { "x" : { "$maxKey" : 1 } }, "shard" : "mongo-9004" }

config.settings

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

mongos> db.settings.find()
{ "_id" : "chunksize", "value" : NumberLong(64) }
{ "_id" : "balancer", "stopped" : false }

其他集合

  • config.tags主要存储sharding cluster标签(tag)相关的信息,以实现根据tag来分布chunk的功能

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

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

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

参考资料

  • MongoDB复制集架构原理

  • MongoDB Sharding简介

  • primary shard

  • enableSharding命令

  • movePrimary命令

  • shardCollection

  • sharding的管理操作

  • 部署sharded cluster

转载地址:https://yq.aliyun.com/articles/32434?spm=a2c4e.11153940.blogcont60096.5.4fb078ddO42glX

转载于:https://blog.51cto.com/xinsir/2357967

mongodb 高可用分布式原理 ---------搭建高可用mongo集群前需要温习的知识-火相关推荐

  1. 二进制搭建kubernetes多master集群【三、配置k8s master及高可用】

    前面两篇文章已经配置好了etcd和flannel的网络,现在开始配置k8s master集群. etcd集群配置参考:二进制搭建kubernetes多master集群[一.使用TLS证书搭建etcd集 ...

  2. Redis高可用之主从复制、哨兵、cluster集群

    一 Redis高可用 1.什么是高可用 在web服务器中,高可用是指服务器可以正常访问的时间,衡量的标准是在多长时间内可以提供正常服务(99.9%.99.99%.99.999%等等). 高可用的计算公 ...

  3. kafka入门:简介、使用场景、设计原理、主要配置及集群搭建

    为什么80%的码农都做不了架构师?>>>    kafka入门:简介.使用场景.设计原理.主要配置及集群搭建(转) 问题导读: 1.zookeeper在kafka的作用是什么? 2. ...

  4. 分布式一致性协议 Gossip 和 Redis 集群原理解析

    分布式一致性协议 Gossip 和 Redis 集群原理解析 Redis 是一个开源的.高性能的 Key-Value 数据库.基于 Redis 的分布式缓存已经有很多成功的商业应用,其中就包括阿里 A ...

  5. Mongodb安装搭建Replica Set+Sharding集群

    2019独角兽企业重金招聘Python工程师标准>>> Mongodb安装搭建Replica Set+Sharding集群 一.简介 Replica Set:复制在为数据提供了冗余同 ...

  6. Docker搭建MongoRocks副本分片集群(Docker Mongodb Rocksdb Replication Sharding)

    Docker搭建MongoRocks副本分片集群 准备 依赖 安装 下载镜像 基本单实例 带配置的单实例 权限配置 docker参数解释 启动命令 rocksdb配置解释 查看启动日志 连接测试 ov ...

  7. kafka入门:简介、使用场景、设计原理、主要配置及集群搭

    李克华 云计算高级群: 292870151 195907286 交流:Hadoop.NoSQL.分布式.lucene.solr.nutch  kafka入门:简介.使用场景.设计原理.主要配置及集群搭 ...

  8. 带你来搭建虚拟机和Redis集群,记得收藏

    1.前言 我们看到分析 Redis 使用或原理的文章不少,但是完整搭建一套独立的 Redis 集群环境的介绍,并不是很多或者说还不够详细. 那么,本文会手把手带着大家搭建一套 Redis 集群环境,R ...

  9. centos redis 升级版本_带你来搭建虚拟机和Redis集群,记得收藏

    来源于公众号Java爱好者社区 , 作者东升的思考 1.前言 我们看到分析 Redis 使用或原理的文章不少,但是完整搭建一套独立的 Redis 集群环境的介绍,并不是很多或者说还不够详细. 那么,本 ...

  10. 华为三台服务器虚拟化做集群怎样做,使用三台云服务器搭建真正的Redis集群

    三台云服务器搭建redis集群# 今天花了一天的时间弄集群redis:遇到了很多坑,从头开始吧 环境讲解: 两台配置:1核2G,另一台:1核1G: 操作系统:Centos 7.6 Redis:3.2. ...

最新文章

  1. Uncaught TypeError: Object [object Object] has no method 'xxx'
  2. REM重复制造MFBF功能
  3. 软件史上最伟大的十大程序员
  4. java和asp.net core,VS 2019教程:创建ASP.NET Core Web App
  5. 科学与技术计算机图片解释,【图片】计算机-科普—都是从网上找的【计算机科学与技术吧】_百度贴吧...
  6. jquery 常见选择器以及一些方法
  7. jquery删除空图片错误图片,$('img[src=]').remove();
  8. mac使用的文章合集 alfred利器
  9. 翠竹林 Java 实现对Sql语句解析
  10. ubuntu20 关闭防火墙_ubuntu中如何关闭防火墙
  11. python爬虫笔记(3)
  12. Oracle 12c的安装
  13. Unity3D相机限制移动范围
  14. android 浏览器 遥控器 光标,论Android智能电视盒子必装应用之——飞视浏览器
  15. 去哪儿12306候补购票怎么用?
  16. win10常用dos命令
  17. 虚拟机如何支持硬件虚拟化
  18. 电赛知识补充——电机篇
  19. vue开发的微信服务号H5内嵌的腾讯地图和导航
  20. 盈透创始人 Thomas Peterffy

热门文章

  1. 从零开始--系统深入学习android(实践-让我们开始写代码-Android框架学习-2. 输入控件)...
  2. Linux服务之批量部署篇
  3. Codeforces Round #468 (Div. 2, based on Technocup 2018 Final Round)
  4. oracle 消除块竞争(hot blocks)
  5. WIN7、WIN8 右键在目录当前打开命令行Cmd窗口(图文)
  6. java 通过 Properties类 读取ini文件 键—值对
  7. com scripting读书笔记
  8. WebService—实现接口发布和客户端调用的几种方式
  9. Python Day2
  10. const char * char * const