在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进程挂掉了,是不是整个集合的查询就没有意义了啊?
发现只要有一个分片挂了,就查询不了数据了。