分片集群

分片组件

   为了能够分担数据库的读写压力,并且解决服务器的磁盘空间的利用情况,可以将数据分布到多台服务器,并且每部分数据都存在副本来保证数据的高可用。实现这样的一个架构称作分片集群。一个分片集群有多个分片组成,并且每个分片都有一个或多个副本。每个分片都是一个独立的副本集。分片集群的结构图如下:

  每个分片集群有三部分组成mongos、mongoconfig和mongodb。  

  mongos

    mongos充当了路由器的角色,负责将客户端的请求路由到分片,但是对于客户端来说这是透明的。mongos为了提高操作数据的效率,会缓存一部分元数据。但是在mongos重启或者新加入一个mongos或者有数据块迁移,才会从配置服务器获取元数据。

  mongoconfig

    配置服务器是一种特殊的mongod,它持有分片集群的元数据,这些元数据描述了分片系统的状态和组织,以及数据库数据的分布情况。

  mongodb

    mongodb是用来存储数据的真正位置,数据库的集合会按照一定的规则分配到多个分片上,每个分片上存储的数据只是一个集合的子集,所有分片上的数据总和为整个数据库的数据。

分片概述

  分片键

     每个集合在分片时,需要通过一个键来划分,这个键是文档中任何索引的单一或者符合字段。集合分片有两种形式:基于范围划分和基于哈希值划分。

  基于范围划分

     字段值在一定范围的文档会落在相同的分片上,例如用户的首字母的范围在[a,z],在按照范围划分后,[a,m]在分片1,(m,z]在分片2。但是也存在一定的缺点,在某一范围的请求过多时,会导致分片的负载过大,使系统没有得到正确的扩展。

  基于哈希值的划分

    哈希划分是根据每个字段值的哈希值分配到指定的片上。这样就会保证即使字段值相近的文档也不会存储在同一个分片上。这样就会保证数据均匀的分布在分片上,但是也会存在一定的缺点,在查询一定范围中的文档时,效率会降低,因为一定范围的文档可能会存在于多个分片。

  数据块

    通过分片键分割的集合组成一定大小的数据块,这些数据块的大小默认为64MB,例如现在有一个博文的帖子,该集合按照日期date进行分片,集合分布在3个分片上,分片1:从最早的时间到2009年7月,分片2:从2009年8月到2011年12月,分片3:从2012年1月到现在。

    1、客户端在查询数据时,首先会访问mongos。

    2、mongos会查询本地路由表,查找该数据存在于哪个分片,并将请求发送到分片3。

    3、分片3会将结果返回给mongos,符合条件的数据可能在多个分片,mongos会将所有复合条件的数据合并后返回到客户端。

    在创建集合时,只有一个数据块存在于一个分片中,数据块的范围为(-∞,+∞),随着数据的不断增多,会将数据按照一定的值进行分块。

数据平衡过程

  数据块划分

    在数据的不断增大,mongo会根据数据块的大小随时进行分块,如果数据块的大小大于64MB就行进行分块,使数据块保持在小于或者等于指定大小。插入和更新操作都会触发划分操作。划分操作会导致配置服务器的元数据修改。

      

 平衡器

   数据块的划分可能会导致集群失衡,出现失衡的情况会触发平衡器。当有一个分片上的数据库多余其他分片,平衡器会将多余的数据块,分配到其他平衡器上,保证每个分片上的数据块相等。集群中的任何一个mongos都可以初始化平衡器程序,在完成数据块从一个数据块到另一个数据块时,会导致配置服务器上元数据的变更,同时在平衡器移动数据库时会对数据库性能造成影响。所以在数据块移动时分为两种策略:

  1、可以在达到一定阈值后,触发平衡器。这个阈值标识分片上最大数量和最小数量之间的差值。

  2、在指定的时间段内进行数据块迁移。

  数据迁移过程:

  1、mongos会发送moveChunk命令到源分片。

  2、源分片在接收到moveChunk命令后,会创建数据块的文档副本,并对副本进行排序。在此期间mongos接收到的客户端请求都会继续路由到源分片,。

  3、目标分片开始从源分片接收数据副本。

  4、一旦所有的数据接收完毕,就会开始初始化目标分片刚才迁移的数据,以保证在此期间产生的数据变更。

  5、一旦同步完成,源分片上的数据就会删除。

集群片键

  片键的好与坏直接关系到整个集群的性能,片键的选择可能会出现一下集中情况:

  小基数片键

    也就是说片键的值只有几个可以存在,集群只能通过这几个值进行分片。但是随着文档的不断增加,分片上的数据不断积累,由于字段值的数量有限,最终导致分片上的数据库的大小不断增大。也就是说一个键有N个值,那就只能有N个数据块,因此也只能有N个分片。例如有一个集合中的每个文档都有一个字段contient这个字段,这个字段只有7个值,Asia、Europe、North America、South America、Africa、Oceania和Antarctica。但是随着数据的不断增多包含7个值中的任何一个值的文档都会不断增大,从而导致每个数据块也在不断增大,这样机会失去分片的意义。

  升序片键

    如时间戳作为片键,随着数据的不断增减,数据块从一个分为两个,但是对数据的插入都会坐落到第二个数据块,当第二个数据块达到一定的大小,就会再次分为两个,同时新数据继续做落到最后一个数据块,该时间戳作为的片键为升序片键。

  随机片键

    当某一个字段的取值是随机的,那么当数据插入时,会随机的分配到多个分片。虽然随着数据的不断增多,数据均匀的分布到分片集群,但是也会对数据库的操作效率变低。

  好片键

    一个好的分片键既要保证良好的数据局部性也不会因为太局部而产生热点。例如{coarselyAsecond:1,search:1}这样的组合键来实现目标,coarselyAsecond字段对应多个数据块,但是search会在对应的多个数据块上搜索到指定的数据,也就是说coarselyAsecond字段对应局部数据,search字段是一个常用的检索字段。

使用集群

  查询中的计数功能

   在查询复合某一条件的文档数时,mongos会将请求发送到每个分片,并将查询的结果合并后返回给客户端。但是当有一个数据块在移动时,数据可能存在于两个分片,这样在查询的文档坐落在两个分片上时,查询的结果可能大于实际的数量。这是mongo目前存在的一个问题,可能在以后的几个版本得到解决。

  唯一索引

    在分片集群中存在各种索引,但是唯一索引除了分片键之外难以实现。例如文档{"_id":ObjectId("89sw89d89cud8we8dw"),“userName”:"abc","email":"1121111111@qq.com"},在这个文档中如果唯一索引是username,在插入文档时搜索所有的分片没有userName=abc的文档,开始插入文档,但是此时其他的客户端也在插入userName=abc的文档,并查询每个分片时也没有出现userName=abc的文档并进行插入工作,两个客户端同时插入userName=abc的文档就很难保证索引的唯一性。分片键能够保证唯一性是因为每个文档会按分片键值存储在一个数据块上。由此可以了解到,在插入文档时,自动生成的id很难保证唯一性,除非id作为分片键。

  更新

   在按照条件进行更新操作时,如果条件不是分片键那么在进行更新时会多所有的分片进行查询并执行更新操作,这样会降低数据库的效率。只有在使用分片键后,查询会落在一个数据块上。所以在更新数据时尽量带有分片键作为条件,否则就会报错。如果不带有分片键,可以执行批量更新来避免报错。

基于标签分片

   1、启动分片集群,启动的步骤为:启动配置服务器,启动路由服务器,启动分片服务器。

   2、将分片标记为标签:sh.addShardTag("分片名称1","标签名称1"),...,sh.addShardTag("分片名称N","标签名称N")。

   3、在某一集合上的所有数据块都放在一个分片上:sh.addTagRange("集合1",{“字段1”:"MinKey"},{"字段1":MaxKey},"标签名称")

   4、如果在此之前使用了分片键,将集合均匀的分布到多个分片,此时就会发生数据块的移动。

  使用标签进行扩展

    当集群中有三个标签(dramas、actions、comedies),三个分片(shard0000、shard0001、shard0002),三个集合(movies.drama、movies.action、movies.comedy),对应结构如下:

    现在需要将action分布在两个分片上,而其他集合分布在两外一个分片上。操作如下:

    1、将标签为dramas和comedies的标签分布到shard0000分片上而actions分布到另外两个分片上。sh.addShardTag("shard0000","comedies"),sh.removeShardTag("shard0002","comedies"),sh.addShardTag("shard0002","actions")。

    2、在经过一段时间后,重新查看数据块的分片会发现集合movies.drama和movies.comedy的数据块全部存在于shard0000上,集合movies.action的数据块存在于shard0001和shard0002上。

分片操作

 1、设置多个分片服务器,并且每个分片服务器都有多个从服务器。

 分片1的primary节点的配置文件:

  所在的服务器的ip为192.168.121.12

dbpath=/usr/local/mongodb01/data  //数据存储位置
logpath=/usr/local/mongodb01/logs  //日志存储位置
port=27020   //实例运行端口
fork=true   //是否后台运行
replSet=db0   //复制集的名称
journal=true   //否否开启journal日志
bind_ip=0.0.0.0  //绑定的ip

 分片1的secondary节点的配置文件:

  所在的服务器的ip为192.168.121.14

dbpath=/usr/local/mongodb01/data  //数据存储位置
logpath=/usr/local/mongodb01/logs  //日志存储位置
port=27019   //实例运行端口
fork=true   //是否后台运行
replSet=db0   //复制集的名称
journal=true   //否否开启journal日志
bind_ip=0.0.0.0  //绑定的ip

 分片2的arbiter节点的配置文件:

  所在的服务器的ip为192.168.121.12

dbpath=/usr/local/mongodb01/data  //数据存储位置
logpath=/usr/local/mongodb01/logs  //日志存储位置
port=27021   //实例运行端口
fork=true   //是否后台运行
replSet=db0   //复制集的名称
journal=true   //否否开启journal日志
bind_ip=0.0.0.0  //绑定的ip

 设置分片1集群的配置:

  rs.initiate({“_id:db0”,“members”:[{"_id":0,"host":"192.168.121.12:27020","priorty":"2"},{"_id":1,"host":"192.168.121.14:27019","priorty":"1"},{"_id":2,"host":"192.168.121.12:27021","priorty":"1","arbiterOnly" : true"}]})

2、将分片2和分片3按照分片1的操作设置为复制集。

  每一个分片都是一个独立的复制集,将所有的分片整合后就是整个mongo数据库。

3、配置configure服务器

  configure服务器与mongodb服务器没有区别,数据库中保存的数据为整个分片集群的配置信息。config服务器在3.2版本之后在配置时需要设置为复制集的模式。

  configure服务器的primary节点配置:

  所在的服务器ip为192.168.121.12

dbpath=/usr/local/mongocfg01/data  //数据存储位置
logpath=/usr/local/mongocfg01/logs  //日志存储位置
port=27018   //实例运行端口
fork=true   //是否后台运行
replSet=cfg0   //复制集的名称
journal=true   //否否开启journal日志
bind_ip=0.0.0.0  //绑定的ip

  configure服务器的secondary节点配置:

  所在服务器的ip为192.168.121.14

dbpath=/usr/local/mongocfg02/data  //数据存储位置
logpath=/usr/local/mongocfg02/logs  //日志存储位置
port=27018   //实例运行端口
fork=true   //是否后台运行
replSet=cfg0   //复制集的名称
journal=true   //否否开启journal日志
bind_ip=0.0.0.0  //绑定的ip

  configure服务器的arbiter节点配置:

  所在服务器的ip为192.168.121.12

dbpath=/usr/local/mongocfg03/data  //数据存储位置
logpath=/usr/local/mongocfg03/logs  //日志存储位置
port=27019   //实例运行端口
fork=true   //是否后台运行
replSet=cfg0   //复制集的名称
journal=true   //否否开启journal日志
bind_ip=0.0.0.0  //绑定的ip  

  configure服务器复制集的配置:

  rs.initiate({“_id:db0”,“members”:[{"_id":0,"host":"192.168.121.12:27018","priorty":"2"},{"_id":1,"host":"192.168.121.14:27018","priorty":"1"},        {"_id":2,"host":"192.168.121.12:27019","priorty":"1","arbiterOnly" : true"}]})

4、配置mongos路由服务器

  在配置路由服务器时,可以配置多个以此保证当其中一个服务器挂掉后,整个业务系统能够正常运行。

  配置内容如下:

  路由服务器的ip为192.168.121.12和192.168.121.14

logpath=/usr/local/mongos01/logs
port=27017
fork=true
configdb=cfg0/192.168.121.12:27018,192.168.121.12:27019,192.168.121.14:27018
bind_ip=0.0.0.0

5、添加分片到集群

  sh.addShard("db0/192.168.121.12:27020")

  sh.addShard("db1/192.168.121.12:27022")

  sh.addShard("db2/192.168.121.14:27021")

  执行sh.status()发现所有的从节点也会主动加入到分片集群中。

6、启动分片集群

  启动所有的配置服务器

  启动所有的路由服务器

  启动所有的分片服务器

7、添加一个新分片

  设置新分片的复制集:primary节点为192.168.121.14:27023,secondary节点为192.168.121.12:27024,arbiter节点为192.168.121.14:27024

  添加新分片到分片集群:db.addShard("db3/192.168.121.14:27024')

  验证是否添加成功,运行db.runCommand({listshards:1})

  查看集合中文档的数量,会发现结合数量在不断增加,此时mongos在进行数据块的平衡。

8、移除一个分片

  在移除分片后,mongos会自动将该分片上的数据块移除,然后才执行移除分片的命令。

  执行移除分片的命令为:db.runCommand({removeShard:"192.168.121.14:27024"})

  执行该命令后,经过一段时间,继续执行移除分片的指令,返回的结果中有一个state字段,值为“ongoing”标识数据块在迁移过程中,值为"complete"标识数据块迁移完成。

  可以执行listshards指令来查看分片集群中各个分片的状态:db.runCommand({listshards:1}),就会发现移除的分片已经不再分片集群中。

9、创建数据库并添加分片集合

  首先在进群中创建数据库eshop和集合users,并插入文档,此时集合只在一个分片上存储,因为没有进行集合分片。

  使数据库支持分片:sh.enableSharding("eshop")

  由于需要为分片集合提供分片键,并且分片键必须是索引,所以需要在分片键上创建索引:db.users.ensureIndex({city:1})。如果分片键是复合键,就需要创建复合索引。

  为分片结合设置分片键:sh.shardCollection("eshop.users",{city:1})。

转载于:https://www.cnblogs.com/youzhongmin/p/8306969.html

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MongoDB的分片集群是一种用于处理大规模数据的解决方案,它将数据分布在多个服务器上,以实现数据的水平扩展和负载均衡。下面是关于MongoDB分片集群的介绍和演示[^1]: 1. 分片集群架构:MongoDB分片集群由以下组件组成: - Shard:每个Shard是一个独立的MongoDB实例,负责存储部分数据。 - Config Server:Config Server存储了分片集群的元数据,包括数据的分片规则和Chunk的位置信息。 - Mongos:Mongos是客户端与分片集群交互的接口,它将客户端的请求路由到正确的Shard上。 2. 分片策略:MongoDB使用分片键将数据分布到不同的Shard上。分片键是一个用于划分数据的字段,例如根据用户ID进行分片。MongoDB提供了多种分片策略,包括范围分片、哈希分片和标签分片。 3. 分片集群的配置和部署:配置一个MongoDB分片集群需要以下步骤: - 部署Shard:在多台服务器上安装和配置MongoDB实例,并将它们作为Shard加入到集群中。 - 部署Config Server:安装和配置Config Server实例,并将它们作为Config Server加入到集群中。 - 配置Mongos:安装和配置Mongos实例,并将它们作为Mongos加入到集群中。 - 配置分片规则:使用MongoDB的命令行工具或驱动程序,配置分片规则和分片键。 4. 演示:以下是一个简单的MongoDB分片集群演示: - 部署3个Shard服务器和2个Config Server服务器。 - 配置Mongos实例并启动。 - 创建一个数据库和集合。 - 配置分片规则,将数据根据分片键进行分片。 - 向集合中插入数据,观察数据如何分布在不同的Shard上。 - 运行查询,观察Mongos如何将查询路由到正确的Shard上。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值