0.5372018.04.22 21:20:07字数 4283阅读 4842html
分片在多台服务器上分布数据的方法, Mongodb使用分片来支持具备很是大的数据集和高吞吐量的操做的部署mongodb
具备大数据集和高吞吐量应用程序的数据库系统,能够挑战单台服务器的容量。
例如,高查询率能够耗尽服务器的cpu容量,工做集大小大于系统的RAM强制磁盘驱动器的I/O容量,shell
有两种方法来解决系统增加:垂直和水平缩放。数据库
垂直缩放 涉及增长的单个服务器的容量,例如使用更强大的CPU,加入更多的RAM,或增长的存储空间量。可用技术中的限制可能限制单个机器对于给定工做负载足够强大。此外,基于云的提供商具备基于可用硬件配置的硬上限。所以,对于垂直缩放存在实际的最大值。编程
包括将系统数据和负载在多个服务器,添加额外的服务器,须要增长容量。虽然单个机器的总速度或容量可能不高,可是每一个机器处理整个工做负载的子集,潜在地提供比单个高速大容量服务器更好的效率。扩展部署的容量仅须要根据须要添加额外的服务器,这能够是比单个机器的高端硬件低的整体成本。权衡是基础设施的复杂性和部署的维护。vim
Mongodb的支持水平扩展,分片。缓存
一、分片目的安全
对于单台数据库服务器,庞大的数据量及高吞吐量的应用程序对它而言无疑是个巨大的挑战。频繁的CRUD操做可以耗尽服务器的CPU资源,快速的数据增加也会让硬盘存储无能为力,最终内存没法知足数据须要致使大量的I/O,主机负载严重。为了解决这种问题,对于数据库系统通常有两种方法:垂直扩展和分片(水平扩展)。bash
【垂直扩展】:添加更多的CPU和存储资源来增长系统性能。这种方式缺点是:拥有大量CPU和RAM资源的高端机器比普通PC机器昂贵得太多,并且单点故障会影响整个系统的服务。服务器
【分片】:相反地,分片将大的数据集分配到多台主机上,每一个分片是一个独立的数据库,这些分片总体上构成一个完整的逻辑数据库。分片减小了每台服务器上的数据操做量,随着集群的增加,每台分片处理愈来愈少的数据,结果,增长了系统总体服务能力。另外,分片还减小了每台服务器须要存储的数据量。
二、MongoDB中的分片
MongoDB经过配置分片集群来支持分片,一个分片集群包括如下几个组件:分片,查询路由,配置服务器
数据划分
MongoDB的数据划分,是以集合级别为标准。分片经过shard key来划分集合数据。
为了对集合分片,你须要指定一个shard key。shard key既能够是集合的每一个文档的索引字段也能够是集合中每一个文档都有的组合索引字段。MongoDB将shard keys值按照块(chunks)划分,而且均匀的将这些chunks分配到各个分片上。MongoDB使用基于范围划分或基于散列划分来划分chunks的。
MongoDB经过shard key值将数据集划分到不一样的范围就称为基于范围划分。对于数值型的shard key:你能够虚构一条从负无穷到正无穷的直线(理解为x轴),每一个shard key 值都落在这条直线的某个点上,而后MongoDB把这条线划分为许多更小的没有重复的范围成为块(chunks),一个chunk就是就某些最小值到最大值的范围。
MongoDB计算每一个字段的hash值,而后用这些hash值创建chunks。
基于范围划分对于范围查询比较高效。假设在shard key上进行范围查询,查询路由很容易可以知道哪些块与这个范围重叠,而后把相关查询按照这个路线发送到仅仅包含这些chunks的分片。可是基于范围划分很容易致使数据不均匀分布,这样会削弱分片集群的功能。例如当shard key是个成直线上升的字段,如时间。那么,全部在给定时间范围内的请求都会映射到相同的chunk,也就是相同的分片上。这种状况下,小部分的分片将会承受大多数的请求,那么系统总体扩展并不理想。
相反的,基于散列划分是以牺牲高效范围查询为代价,它可以均匀的分布数据,散列值可以保证数据随机分布到各个分片上。
MongoDB容许DBA们经过标签标记分片的方式直接平衡数据分布策略,DBA能够建立标签而且将它们与shard key值的范围进行关联,而后分配这些标签到各个分片上,最终平衡器转移带有标签标记的数据到对应的分片上,确保集群老是按标签描述的那样进行数据分布。标签是控制平衡器行为及集群中块分布的主要方法
四、维持数据分布平衡
新加入的数据及服务器都会致使集群数据分布不平衡,MongoDB采用两种方式确保数据分布的平衡:
拆分是一个后台进程,防止块变得太大。当一个块增加到指定块大小的时候,拆分进程就会块一分为二,整个拆分过程是高效的。不会涉及到数据的迁移等操做。
平衡器是一个后台进程,管理块的迁移。平衡器可以运行在集群任何的mongd实例上。当集群中数据分布不均匀时,平衡器就会将某个分片中比较多的块迁移到拥有块较少的分片中,直到数据分片平衡为止。举个例子:若是集合users有100个块在分片1里,50个块在分片2中,那么平衡器就会将分片1中的块迁移到分片2中,直到维持平衡。
分片采用后台操做的方式管理着源分片和目标分片之间块的迁移。在迁移的过程当中,源分片中的块会将全部文档发送到目标分片中,而后目标分片会获取并应用这些变化。最后,更新配置服务器上关于块位置元数据。
添加新分片到集群中会产生数据不平衡,由于新分片中没有块,当MongoDB开始迁移数据到新分片中时,等到数据分片平衡恐怕须要点时间。
当删除一个分片时,平衡器将会把分片中全部块迁移到另外一个分片中,在完成这些迁移并更新元数据后,你就能够安全的删除分片了。
一个mongodb分片集群由如下几部分组成
12.jpg
shard
每一个shard包含分片数据的子集,每一个shard能够部署一个副本集13.jpg
mongos
MongoS充当一个查询的路由器,提供客户端应用程序和所述分片簇之间的接口,mongos做为数据库集群请求的入口,全部的请求都是经过mongos来进行协调的,不须要在应用程序添加一个路由选择器,mongos本身就是一个请求分发中心,它负责把对应的数据请求转发到对应的shard服务器上,在生产环境中一般有多个monogs做为请求的入口,防止其中一个挂掉全部mongos请求都没有办法操做config servers
为集群配置的服务器存储元数据和配置设置,从Mongodb3.4开始,配置服务器必须部署为复制集,mongos自己没有物理存储分片服务器和数据路由信息,只是缓存在内存当中,配置服务器则实际存储这些数据,mongos第一次启动或者关掉重启会从configserver中加载配置信息,之后若是配置信息有变化会经过全部的mongos更新本身的状态,这样mongs就能继续准确路由,在生产环境中一般有多个config server配置服务器,由于它存储了分片路由的元数据,若是就一个若是挂掉一个,整个mongodb基础就会挂掉。片键
片键
一、在分发集合中文件时,mongodb的分区使用的收集片键关键,在片键由存在目标集合中的每一个文档中的一个不可变或多个字段
二、在分割集合的时候选择片键,<font color=red size=4>分片键完成以后是不能更改的</font>,分片集合只能有1个片键,到片键的非空集合,集合必须有一个索引,与片键启动,对于空空集合,若是集合还没有具备指定分片键的相关索引,则Mongodb会建立索引
三、分片键的选择会影响分片集群的性能和效率以及可伸缩性,具备最佳可能的硬件能够经过分片达到瓶颈,片键和其支持指数的选择也能够影响数据的拆分,但集群可使用
四、片键决定了集群中一个集合的文件咋不一样的片键中的分布,片键字段必须被索引,且在集合中的每条记录都不能为空,能够是单个字段或者是复合字段
五、Mongodb使用片键的范围是吧数据分布在分片中,每一个范围,又称为数据块,定义了一个不重叠的片键范围Mongodb把数据块与他们存储的文档分布到集群中的不一样分布中,当一个数据块的大小超过数据块最大大小的时候,Mongodb会宜聚片键的范围将数据块分裂为更小的数据块
14.png
sh.shardCollection()
sh.shardCollection(namespace, key)
二、哈希片键使用单字段的哈希索引进行数据在分片之间的平均分发,除数取余
和一致性哈希
三、被选为片键的字段必须有足够大的基数,或者有足够多的不一样的值,对于单调的递增的字段若是ObjectID
或是时间戳,哈希索引效果更好
四、若是在一个空集合建立哈希片键,Mongodb会自动建立并迁移数据块,以保证每一个分片上都有两个数据块,也能够执行shardCollection
指定numInitialChunks
参数以控制初始化时Mongodb建立数据块数目,或者手动调用split
命令在分片上分裂数据块
五、对使用了哈希片键分片的集合进行请求时,Mongodb会自动计算哈希值,应用不须要解析哈希值
配置config server 副本集
[root@My-Dev db2]# vim config1.conf [root@My-Dev db1]# vim configsvr.conf logpath=/home/mongodb/test/db1/log/db1.log pidfilepath=/home/mongodb/test/db1/db1.pid logappend=true port=30000 fork=true dbpath=/home/mongodb/test/db1/data configsvr=true # 在配置文件添加此项就行 oplogSize=512 replSet=config
[root@My-Dev db2]# vim config2.conf logpath=/home/mongodb/test/db2/log/db2.log pidfilepath=/home/mongodb/test/db2/db2.pid logappend=true port=30001 fork=true dbpath=/home/mongodb/test/db2/data oplogSize=512 replSet=config configsvr=true
[root@My-Dev db2]# vim config3.conf logpath=/home/mongodb/test/db3/log/db3.log pidfilepath=/home/mongodb/test/db3/db3.pid logappend=true port=30002 fork=true dbpath=/home/mongodb/test/db3/data oplogSize=512 replSet=config configsvr=true
[root@My-Dev bin]# ./mongod -f /home/mongodb/test/db1/config1.conf about to fork child process, waiting until server is ready for connections. forked process: 5260 child process started successfully, parent exiting [root@My-Dev bin]# ./mongod -f /home/mongodb/test/db2/config2.conf about to fork child process, waiting until server is ready for connections. forked process: 5202 child process started successfully, parent exiting [root@My-Dev bin]# ./mongod -f /home/mongodb/test/db3/config3.conf about to fork child process, waiting until server is ready for connections. forked process: 4260 child process started successfully, parent exiting
> use admin switched to db admin > config = { _id:"config",members:[ {_id:0,host:"conf1:30000"}, {_id:1,host:"conf2:30001"}, {_id:2,host:"conf3:30002"}] } #定义副本集 { "_id" : "config", "members" : [ { "_id" : 0, "host" : "conf1:30000" }, { "_id" : 1, "host" : "conf2:30001" }, { "_id" : 2, "host" : "conf3:30002" } ] } > rs.initiate(config) #初始化副本集 { "ok" : 1 }
配置mongos
config server
必须是复制集才行,结果个人版本是3.4最新的版本,因此说还须要添加两台confi server
[root@My-Dev db4]# vim mongos.conf logpath=/home/mongodb/test/db4/log/db4.log pidfilepath=/home/mongodb/test/db4/db4.pid logappend=true port=40004 fork=true configdb=mongos/172.17.237.33:30000,172.17.237.34:30001,172.17.237.36:30002 #若是有多个mongo confi的话就用逗号分隔开
[root@My-Dev bin]# ./mongos -f /home/mongodb/test/db4/mongos.conf about to fork child process, waiting until server is ready for connections. forked process: 6268 child process started successfully, parent exiting
shard2副本集集群部署
[root@My-Dev db8]# more shard21.conf logpath=/home/mongodb/test/db8/log/db8.log pidfilepath=/home/mongodb/test/db8/db8.pid directoryperdb=true logappend=true port=60000 fork=true dbpath=/home/mongodb/test/db8/data oplogSize=512 replSet=sha shardsvr=true [root@My-Dev db9]# more shard22.conf logpath=/home/mongodb/test/db9/log/db9.log pidfilepath=/home/mongodb/test/db9/db9.pid directoryperdb=true logappend=true port=60001 fork=true dbpath=/home/mongodb/test/db9/data oplogSize=512 replSet=sha shardsvr=true [root@My-Dev db10]# more shard23.conf logpath=/home/mongodb/test/db10/log/db10.log pidfilepath=/home/mongodb/test/db10/db10.pid directoryperdb=true logappend=true port=60002 fork=true dbpath=/home/mongodb/test/db10/data oplogSize=512 replSet=sha shardsvr=true
[root@My-Dev bin]# ./mongod -f /home/mongodb/test/db8/shard21.conf [root@My-Dev bin]# ./mongod -f /home/mongodb/test/db9/shard22.conf [root@My-Dev bin]# ./mongod -f /home/mongodb/test/db10/shard23.conf
> use admin switched to db admin > sha = { _id:"sha",members:[ {_id:0,host:"sha1:60000"}, {_id:1,host:"sha2:60001"}, {_id:2,host:"sha3:60002"}]} { "_id" : "sha", "members" : [ { "_id" : 0, "host" : "sha1:60000" }, { "_id" : 1, "host" : "sha2:60001" }, { "_id" : 2, "host" : "sha3:60002" } ] } > rs.initiate(sha) { "ok" : 1 }
shard1副本集集群部署
[root@My-Dev db5]# vim shard1.conf logpath=/home/mongodb/test/db5/log/db5.log pidfilepath=/home/mongodb/test/db5/db5.pid directoryperdb=true logappend=true port=50000 fork=true dbpath=/home/mongodb/test/db5/data oplogSize=512 replSet=shard shardsvr=true [root@My-Dev db6]# vim shard2.conf logpath=/home/mongodb/test/db6/log/db6.log pidfilepath=/home/mongodb/test/db6/db6.pid directoryperdb=true logappend=true port=50001 fork=true dbpath=/home/mongodb/test/db6/data oplogSize=512 replSet=shard shardsvr=true [root@My-Dev db7]# vim shard3.conf logpath=/home/mongodb/test/db7/log/db7.log pidfilepath=/home/mongodb/test/db7/db7.pid directoryperdb=true logappend=true port=50002 fork=true dbpath=/home/mongodb/test/db7/data oplogSize=512 replSet=shard shardsvr=true
[root@My-Dev bin]# ./mongod -f /home/mongodb/test/db7/shard1.conf [root@My-Dev bin]# ./mongod -f /home/mongodb/test/db7/shard2.conf [root@My-Dev bin]# ./mongod -f /home/mongodb/test/db7/shard3.conf
> use admin switched to db admin > shard = { _id:"shard",members:[ {_id:0,host:"shard1:50000"}, {_id:1,host:"shard2:50001"}, {_id:2,host:"shard3:50002"}] } { "_id" : "shard", "members" : [ { "_id" : 0, "host" : "shard1:50000" }, { "_id" : 1, "host" : "shard2:50001" }, { "_id" : 2, "host" : "shard3:50002" } ] } > rs.initiate(shard) { "ok" : 1 }
分片配置
分片集合中是否有数据
默认第一个添加的shard就是主shard,存放没有被分割的shard就是主shard
在建立分片的时,必须在索引中建立的,若是这个集合中有数据,则首先本身先建立索引,而后进行分片,若是是分片集合中没有数据的话,则就不须要建立索引,就能够分片
登录mongos配置分片,向分区集群中添加shard服务器和副本集
[root@My-Dev bin]# ./mongo mongos:40004 #登录到mongos中 mongos> sh.status() #查看分片状态 --- Sharding Status --- sharding version: { "_id" : 1, "minCompatibleVersion" : 5, "currentVersion" : 6, "clusterId" : ObjectId("589b0cff36b0915841e2a0a2") } shards: active mongoses: "3.4.1" : 1 autosplit: Currently enabled: yes balancer: Currently enabled: yes Currently running: no Balancer lock taken at Wed Feb 08 2017 20:20:16 GMT+0800 (CST) by ConfigServer:Balancer Failed balancer rounds in last 5 attempts: 0 Migration Results for the last 24 hours: No recent migrations databases:
#首先要登录到shard副本集中查看那个是主节点,本次实验室使用了两个shard副本集 sh.addShard("<replSetName>/主节点IP/port") mongos> sh.addShard("shard/shard1:50000") { "shardAdded" : "shard", "ok" : 1 } mongos> sh.addShard("sha/sha:60000") { "shardAdded" : "shard", "ok" : 1 } mongos> sh.status() #查看分片集群已经成功把shard加入分片中 --- Sharding Status --- sharding version: { "_id" : 1, "minCompatibleVersion" : 5, "currentVersion" : 6, "clusterId" : ObjectId("589b0cff36b0915841e2a0a2") } shards: { "_id" : "sha", "host" : "sha/sha1:60000,sha2:60001,sha3:60002", "state" : 1 } { "_id" : "shard", "host" : "shard/shard1:50000,shard2:50001,shard3:50002", "state" : 1 } active mongoses: "3.4.1" : 1 autosplit: Currently enabled: yes balancer: Currently enabled: yes Currently running: no Balancer lock taken at Wed Feb 08 2017 20:20:16 GMT+0800 (CST) by ConfigServer:Balancer Failed balancer rounds in last 5 attempts: 5 Last reported error: Cannot accept sharding commands if not started with --shardsvr Time of Reported error: Thu Feb 09 2017 17:42:21 GMT+0800 (CST) Migration Results for the last 24 hours: No recent migrations databa
mongos> sh.enableSharding("zhao") #指定zhao数据库中使用分片 { "ok" : 1 } mongos> sh.shardCollection("zhao.call",{name:1,age:1}) #在zhao数据库和call集合中建立了name和age为升序的片键 { "collectionsharded" : "zhao.call", "ok" : 1 }
sh.status()
信息mongos> sh.status() --- Sharding Status --- sharding version: { "_id" : 1, "minCompatibleVersion" : 5, "currentVersion" : 6, "clusterId" : ObjectId("589b0cff36b0915841e2a0a2") } shards: { "_id" : "sha", "host" : "sha/sha1:60000,sha2:60001,sha3:60002", "state" : 1 } { "_id" : "shard", "host" : "shard/shard1:50000,shard2:50001,shard3:50002", "state" : 1 } active mongoses: "3.4.1" : 1 autosplit: Currently enabled: yes balancer: Currently enabled: yes Currently running: no Balancer lock taken at Wed Feb 08 2017 20:20:16 GMT+0800 (CST) by ConfigServer:Balancer Failed balancer rounds in last 5 attempts: 5 Last reported error: Cannot accept sharding commands if not started with --shardsvr Time of Reported error: Thu Feb 09 2017 17:56:02 GMT+0800 (CST) Migration Results for the last 24 hours: No recent migrations databases: { "_id" : "zhao", "primary" : "shard", "partitioned" : true } zhao.call shard key: { "name" : 1, "age" : 1 } unique: false balancing: true chunks: shard 1 { "name" : { "$minKey" : 1 }, "age" : { "$minKey" : 1 } } -->> { "name" : { "$maxKey" : 1 }, "age" : { "$maxKey" : 1 } } on : shard Timestamp(1, 0)
mongos> for ( var i=1;i<10000000;i++){db.call.insert({"name":"user"+i,age:i})};
mongos> sh.status() --- Sharding Status --- sharding version: { "_id" : 1, "minCompatibleVersion" : 5, "currentVersion" : 6, "clusterId" : ObjectId("589b0cff36b0915841e2a0a2") } shards: { "_id" : "sha", "host" : "sha/sha1:60000,sha2:60001,sha3:60002", "state" : 1 } { "_id" : "shard", "host" : "shard/shard1:50000,shard2:50001,shard3:50002", "state" : 1 } active mongoses: "3.4.1" : 1 autosplit: Currently enabled: yes balancer: Currently enabled: yes Currently running: no Balancer lock taken at Wed Feb 08 2017 20:20:16 GMT+0800 (CST) by ConfigServer:Balancer Failed balancer rounds in last 5 attempts: 5 Last reported error: Cannot accept sharding commands if not started with --shardsvr Time of Reported error: Thu Feb 09 2017 17:56:02 GMT+0800 (CST) Migration Results for the last 24 hours: 4 : Success databases: { "_id" : "zhao", "primary" : "shard", "partitioned" : true } zhao.call shard key: { "name" : 1, "age" : 1 } unique: false balancing: true chunks: #数据已经分片到两个chunks里面了 sha 4 shard 5 { "name" : { "$minKey" : 1 }, "age" : { "$minKey" : 1 } } -->> { "name" : "user1", "age" : 1 } on : sha Timestamp(4, 1) { "name" : "user1", "age" : 1 } -->> { "name" : "user1", "age" : 21 } on : shard Timestamp(5, 1) { "name" : "user1", "age" : 21 } -->> { "name" : "user1", "age" : 164503 } on : shard Timestamp(2, 2) { "name" : "user1", "age" : 164503 } -->> { "name" : "user1", "age" : 355309 } on : shard Timestamp(2, 3) { "name" : "user1", "age" : 355309 } -->> { "name" : "user1", "age" : 523081 } on : sha Timestamp(3, 2) { "name" : "user1", "age" : 523081 } -->> { "name" : "user1", "age" : 710594 } on : sha Timestamp(3, 3) { "name" : "user1", "age" : 710594 } -->> { "name" : "user1", "age" : 875076 } on : shard Timestamp(4, 2) { "name" : "user1", "age" : 875076 } -->> { "name" : "user1", "age" : 1056645 } on : shard Timestamp(4, 3) { "name" : "user1", "age" : 1056645 } -->> { "name" : { "$maxKey" : 1 }, "age" : { "$maxKey" : 1 } } on : sha Timestamp(5, 0)
true
是均匀的false
不是均匀的mongos> sh.getBalancerState() true
选择sharing kes'
注意点
shard
和移除shard
mongos> sh.addShard("sha4/192.168.2.10:21001")
Balancer
mongos> sh.startBalancer()
#设置时间窗口 db.settings.update({ _id : "balancer" }, { $set : { activeWindow : { start : "23:00", stop : "6:00" } } }, true )
# 查看Balancer时间窗口 mongos> db.settings.find(); { "_id" : "balancer", "activeWindow" : { "start" : "23:00", "stop" : "6:00" }, "stopped" : false } mongos> sh.getBalancerWindow() { "start" : "23:00", "stop" : "6:00" }
mongos> db.settings.update({ "_id" : "balancer" }, { $unset : { activeWindow : 1 }}); mongos> db.settings.find(); { "_id" : "chunksize", "value" : 10 } { "_id" : "balancer", "stopped" : false }
在shell脚本中执行mongodb
[root@My-Dev ~]# echo -e "use zhao \n db.call.find()" |mongo --port 60001
Mongodb片键的添加
mongos> use admin switched to db admin mongos> db.runCommand({"enablesharding":"zl"}) #建立zl库中 { "ok" : 1 } mongos> db.runCommand(db.runCommand({"shardcollection":"$ent.t_srvappraise_back","key")
#!/bin/bash url=10.241.96.155 port=30000 ent=test1 ./mongo $url:$port/admin <<EOF db.runCommand({"enablesharding":"$ent"}); db.runCommand({"shardcollection":"$ent.t_srvappraise_back","key":{"sa_seid":"hashed"}}) exit; EOF
5人点赞
拥有33钻 (约5.84元)
关注
"小礼物走一走,来简书关注我"
赞扬
所有评论0只看做者
按时间倒序
按时间正序
1、环境说明: 一、操做系统:CentOS Linux release 7.4.1708 二、mongodb版本:...
MongoDB基础请参考:http://blog.51cto.com/kaliarch/2044423 Mongo...
配置服务器,所有设置为静态地址 转到/home目录,建立一个mongo目录用作实验,咱们须要建立以下的目录层级和空...
随着物质生活愈来愈丰富,人们生活水平不断提升,消费观念也随之改变。从过去人们只需求物质的实用性,到追求品牌消费,后...
摘要:赚个一个亿的小目标不到三分钟就完成,让很多服装行家羡慕妒忌恨,服装生意盈亏参半,MCmore助你正确拥抱服装...