🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
在mongodb里面存在另一种集群,就是分片技术,跟sql server的表分区类似,我们知道当数据量达到T级别的时候,我们的磁盘,内存就吃不消了,针对这样的场景我们该如何应对。 ## 分片 mongodb采用将集合进行拆分,然后将拆分的数据均摊到几个片上的一种解决方案。图例分析: <!--more--> ``` 从服务器1 从服务器2 \ / 路由服务器mongods <——> config服务器 | | 客户端 ``` 下面我对这张图解释一下: `客户端`:客户端肯定说,你数据库分片不分片跟我没关系,我叫你干啥就干啥,没什么好商量的。 `mongos`:首先我们要了解”片键“的概念,也就是说拆分集合的依据是什么?mongos就是一个路由服务器,它会根据管理员设置的“片键”将数据分摊到自己管理的mongod集群,数据和片的对应关系以及相应的配置信息保存在"config服务器"上。 `从服务器`:一个普通的数据库实例,如果不分片的话,我们会直接连上mongod。 ## 实战 首先我们准备4个mongodb程序,我这里是均摊在C,D,E,F盘上,当然你也可以做多个文件夹的形式(下面将采用目录的形式mongodb、mongodb2、mongodb3、mongodb4对应C,D,E,F盘)。 mongodb ---config --port 2222 mongodb1 ---mongos --port 3333 mongodb2 ---mongod --port 4444 mongodb3 ---mongod --port 5555 1:开启config服务器 先前也说了,mongos要把mongod之间的配置放到config服务器里面,理所当然首先开启它,我这里就建立2222端口。 ``` D:\Projects\mongodb\bin>mongod --dbpath=D:\Projects\mongodb\db --port 2222 ``` 2: 开启mongos服务器 这里要注意的是我们开启的是mongos,不是mongod,同时指定下config服务器,这里我就开启D盘上的mongodb,端口3333。 ``` D:\Projects\mongodb2\bin>mongos --port 3333 --configdb=127.0.0.1:2222 ``` 3:启动mongod服务器 对分片来说,也就是要添加片了,这里开启E,F盘的mongodb,端口为:4444,5555。 ``` mongod --dbpath=D:\Projects\mongodb3\db --port 4444 mongod --dbpath=D:\Projects\mongodb4\db --port 5555 2015-07-04T10:34:15.394+0800 I NETWORK [initandlisten] waiting for connections on port 4444 2015-07-04T10:35:35.372+0800 I NETWORK [initandlisten] waiting for connections on port 5555 ``` 4: 服务配置 a. 先前图中也可以看到,我们client直接跟mongos打交道,也就说明我们要连接mongos服务器,然后将4444,5555的mongod交给mongos,添加分片也就是addshard()。 ``` D:\Projects\mongodb\bin>mongo 127.0.0.1:3333/admin connecting to: 127.0.0.1:3333/admin mongos> mongos> db.runCommand({"addshard":"127.0.0.1:4444","allowLocal":true}) { "shardAdded" : "shard0000", "ok" : 1 } mongos> db.runCommand({"addshard":"127.0.0.1:5555","allowLocal":true}) { "shardAdded" : "shard0001", "ok" : 1 } ``` 这里要注意的是,在addshard中,我们也可以添加副本集,这样能达到更高的稳定性。 b. 片已经集群了,但是mongos不知道该如何切分数据,也就是我们先前所说的片键,在mongodb中设置片键要做两步: 1)开启数据库分片功能,命令很简单 enablesharding(),这里我就开启test数据库。 2)指定集合中分片的片键,这里我就指定为test.montest.name字段。 ``` db.runCommand({"enablesharding":"test"}) db.runCommand({"shardcollection":"test.montest", "key":{"name":1}}) ``` 5: 查看效果 好了,至此我们的分片操作全部结束,接下来我们通过mongos向mongodb插入1w记录,然后通过printShardingStatus命令 查看mongodb的数据分片情况。 ``` for(var i=0;i<10000;i++){ db.montest.insert({"name":"yjc"+i, "age":i}); } mongos> db.montest.count() 10000 mongos> db.printShardingStatus() --- Sharding Status --- sharding version: { "_id" : 1, "minCompatibleVersion" : 5, "currentVersion" : 6, "clusterId" : ObjectId("559745db7ba8ba85959c9bfb") } shards: { "_id" : "shard0000", "host" : "127.0.0.1:4444" } { "_id" : "shard0001", "host" : "127.0.0.1:5555" } balancer: Currently enabled: yes Currently running: no Failed balancer rounds in last 5 attempts: 0 Migration Results for the last 24 hours: 1 : Success databases: { "_id" : "admin", "partitioned" : false, "primary" : "config" } { "_id" : "test", "partitioned" : true, "primary" : "shard0000" } test.montest shard key: { "name" : 1 } chunks: shard0000 2 shard0001 1 { "name" : { "$minKey" : 1 } } -->> { "name" : "yjc1" } on : shard0001 Timestamp(2, 0) { "name" : "yjc1" } -->> { "name" : "yjc6" } on : shard0000 Timestamp(2, 1) { "name" : "yjc6" } -->> { "name" : { "$maxKey" : 1 } } on : shard0000 Timestamp(1, 3) ``` 这里主要看三点信息: 1)shards:我们清楚的看到已经别分为两个片了,shard0000和shard0001。 2)databases: 这里有个partitioned字段表示是否分区,这里清楚的看到test已经分区。 3)chunks:这个很有意思,我们发现集合被砍成四段: 无穷小 —— yjc , yjc1 —— yjc6, yjc6 —— 无穷大。 分区情况为:2:1,从后面的 on shardXXXX也能看得出。 ## 后记 问题: 1 在现有的数据库上做分片,怎么做? 2 一个分片Mongod进程挂掉了,是不是整个集合的查询就没有意义了啊? 发现只要有一个分片挂了,就查询不了数据了。