这是一种将海量的数据水平扩展的数据库集群系统,数据分表存储在sharding的各个节点上,使用者通过简单的配置就可以很方便地构建一个分布式MongoDB集群。
MongoDB 的数据分块称为 chunk。每个 chunk 都是 Collection 中一段连续的数据记录,通常最大尺寸是 200MB,超出则生成新的数据块。
要构建一个 MongoDB Sharding Cluster,需要三种角色:
Shard Server
即存储实际数据的分片,每个Shard可以是一个mongod实例,也可以是一组mongod实例构成的Replica Set。为了实现每个Shard内部的auto-failover,MongoDB官方建议每个Shard为一组Replica Set。
Config Server
为了将一个特定的collection存储在多个shard中,需要为该collection指定一个shard key,例如{age: 1} ,shard key可以决定该条记录属于哪个chunk。Config Servers就是用来存储:所有shard节点的配置信息、每个chunk的shard key范围、chunk在各shard的分布情况、该集群中所有DB和collection的sharding配置信息。
Route Process
这是一个前端路由,客户端由此接入,然后询问Config Servers需要到哪个Shard上查询或保存记录,再连接相应的Shard进行操作,最后将结果返回给客户端。客户端只需要将原本发给mongod的查询或更新请求原封不动地发给Routing Process,而不必关心所操作的记录存储在哪个Shard上。
下面我们在同一台物理机器上构建一个简单的 Sharding Cluster:
架构图如下:
在同一台机器上模拟一个配置服务器,一个mongos服务器,2个分片(每个分片是单实例)
理应在每台服务器上都下载解压mongodb.由于这里都在同一台机器上模拟操作,故只需解压一次。
tar -xvf mongodb-linux-x86_64-2.6.9.tgz
[root@pc download]# mv mongodb-linux-x86_64-2.6.9 /data/mongodb
为mongodb创建数据库存放的位置和日志文件
[root@pc mongodb]# cd /data/mongodb/
[root@pc mongodb]# mkdir data
[root@pc mongodb]# touch logs
[root@pc mongodb]# ls -ltr
total 68
-rw-r--r-- 1 1046 1046 1359 Mar 23 22:49 README
-rw-r--r-- 1 1046 1046 34520 Mar 23 22:49 GNU-AGPL-3.0
-rw-r--r-- 1 1046 1046 17793 Mar 23 22:49 THIRD-PARTY-NOTICES
drwxr-xr-x 2 root root 4096 Jul 15 13:26 bin
drwxr-xr-x 2 root root 4096 Jul 15 13:34 data
-rw-r--r-- 1 root root 0 Jul 15 13:34 logs
#建配置信息服务器数据文件目录
[root@pc download]# mkdir -p /dbs/config
#建分片目录
mkdir -p /dbs/shard1
mkdir -p /dbs/shard2
#建日志目录
mkdir /logs
#建日志文件
touch /logs/config.log
touch mongos.log
touch shard1.log
touch shard2.log
[root@pc dbs]# vi /root/.bash_profile
在PATH行末尾添加:
:/data/mongodb/bin
[root@pc dbs]# source /root/.bash_profile
配置服务器需要最先启动,mongos服务器需要用到上面的配置信息。配置服务器的启动就像普通mongod一样。
配置服务器不需要很多空间和资源(200MB实际数据大约占1KB的配置空间)
[root@pc dbs]# mongod --dbpath=/dbs/config --logpath=/logs/config.log --fork --port 1000
about to fork child process, waiting until server is ready for connections.
forked process: 5055
child process started successfully, parent exiting
[root@pc ~]# ps -ef | grep mongo
root 9691 1 3 22:31 ? 00:00:00 mongod --dbpath=/dbs/config --logpath=/logs/config.log --fork --port 1000
[root@pc ~]# mongos --port 1001 --logpath=/logs/mongos.log --configdb=192.168.6.51:1000 --fork
2015-07-16T22:32:36.776-0700 warning: running with 1 config server should be done only for testing purposes and is not recommended for production
about to fork child process, waiting until server is ready for connections.
forked process: 9716
child process started successfully, parent exiting
--configdb这里记录的是配置服务器所在IP和端口号。
配置--conigdb的时候ip地址不能填localhost或127.0.0.1否则添加分片时会返回如下错误信息:
1. { 2. "ok" : 0, 3. "errmsg" : "can't use localhost as a shard since all shards need to communicate. either use all shards and configdbs in localhost or all in actual IPs host: 192.168.6.51:1000 isLocalHost:0" 4. }
#分片1
[root@pc ~]# mongod --dbpath=/dbs/shard1 --logpath=/logs/shard1.log --fork --port 1002
about to fork child process, waiting until server is ready for connections.
forked process: 10583
child process started successfully, parent exiting
#分片2
[root@pc ~]# mongod --dbpath=/dbs/shard2 --logpath=/logs/shard2.log --fork --port 1003
about to fork child process, waiting until server is ready for connections.
forked process: 10659
child process started successfully, parent exiting
#注意:添加分片和切分数据都是在mongos服务器上进行操作的。
登录mongos服务器,
[root@pc mongodb]# mongo localhost:1001/admin
MongoDB shell version: 2.6.9
connecting to: localhost:1001/admin
#添加分片
mongos> db.runCommand({addshard:"localhost:1002",allowLocal:true });
{ "shardAdded" : "shard0000", "ok" : 1 }
mongos> db.runCommand({addshard:"localhost:1003",allowLocal:true });
{ "shardAdded" : "shard0001", "ok" : 1 }
#查看所有的片
mongos> use config;
switched to db config
mongos> db.shards.find();
{ "_id" : "shard0000", "host" : "localhost:1002" }
{ "_id" : "shard0001", "host" : "localhost:1003" }
默认的是不会将存储的每条数据进行分片处理,需要在数据库和集合的粒度上都开启分片功能。
这里以dba.b为例
mongos> use dba;
switched to db dba
mongos> db.createCollection("b");
{ "ok" : 1 }
mongos> use admin;
switched to db admin
mongos> db.runCommand({"enablesharding":"dba"});
{ "ok" : 1 }
mongos> db.runCommand({"shardcollection":"dba.b","key":{"id":1}})
{ "collectionsharded" : "dba.b", "ok" : 1 }
注意:需要切换到admin库执行命令。
片键:上面的key就是所谓的片键(shard key)。MongoDB不允许插入没有片键的文档。但是允许不同文档的片键类型不一样,MongoDB内部对不同类型有一个排序:
mongos> use config;
switched to db config
mongos> db.databases.find();
{ "_id" : "admin", "partitioned" : false, "primary" : "config" }
{ "_id" : "dba", "partitioned" : true, "primary" : "shard0000" }
可以看到dba这个库分片了。
mongos> db.chunks.find();
{ "_id" : "dba.b-id_MinKey", "lastmod" : Timestamp(1, 0), "lastmodEpoch" : ObjectId("55a8c850fe175819f8525593"), "ns" : "dba.b", "min" : { "id" : { "$minKey" : 1 } }, "max" : { "id" : { "$maxKey" : 1 } }, "shard" : "shard0000" }
Chunks:理解MongoDB分片机制的关键是理解Chunks。mongodb不是一个分片上存储一个区间,而是每个分片包含多个区间,这每个区间就是一个块。
mongos> use dba;
switched to db dba
mongos> for(i=0;i<100000;i++){ db.b.insert({"id":i,"Name":"baidandan","Date":new Date()}); }
WriteResult({ "nInserted" : 1 })
mongos> use config;
switched to db config
mongos> db.chunks.find();
{ "_id" : "dba.b-id_MinKey", "lastmod" : Timestamp(2, 1), "lastmodEpoch" : ObjectId("55a8c850fe175819f8525593"), "ns" : "dba.b", "min" : { "id" : { "$minKey" : 1 } }, "max" : { "id" : 0 }, "shard" : "shard0000" }
{ "_id" : "dba.b-id_0.0", "lastmod" : Timestamp(1, 3), "lastmodEpoch" : ObjectId("55a8c850fe175819f8525593"), "ns" : "dba.b", "min" : { "id" : 0 }, "max" : { "id" : 5562 }, "shard" : "shard0000" }
{ "_id" : "dba.b-id_5562.0", "lastmod" : Timestamp(2, 0), "lastmodEpoch" : ObjectId("55a8c850fe175819f8525593"), "ns" : "dba.b", "min" : { "id" : 5562 }, "max" : { "id" : { "$maxKey" : 1 } }, "shard" : "shard0001" }
我们可以看到现在有三个块:(-∞,0)在shard0000上,[0,5562)在shard0000上和[5562,+ ∞)在shard0001上。
数据已经被自动分配到了这两个片上面。
Note:通过sh.status()可以很直观的查看当前整个集群的分片情况,类似如下:
mongos> sh.status();
--- Sharding Status ---
sharding version: {
"_id" : 1,
"version" : 4,
"minCompatibleVersion" : 4,
"currentVersion" : 5,
"clusterId" : ObjectId("55a89388fe175819f8524cc2")
}
shards:
{ "_id" : "shard0000", "host" : "localhost:1002" }
{ "_id" : "shard0001", "host" : "localhost:1003" }
databases:
{ "_id" : "admin", "partitioned" : false, "primary" : "config" }
{ "_id" : "dba", "partitioned" : true, "primary" : "shard0000" }
dba.b
shard key: { "id" : 1 }
chunks:
shard0000 2
shard0001 1
{ "id" : { "$minKey" : 1 } } -->> { "id" : 0 } on : shard0000 Timestamp(2, 1)
{ "id" : 0 } -->> { "id" : 5562 } on : shard0000 Timestamp(1, 3)
{ "id" : 5562 } -->> { "id" : { "$maxKey" : 1 } } on : shard0001 Timestamp(2, 0)
在分片服务器上查看下数据
--分片1
[root@pc config]# mongo localhost:1002/admin
MongoDB shell version: 2.6.9
connecting to: localhost:1002/admin
> show dbs;
admin (empty)
dba 0.078GB
local 0.078GB
> use dba;
switched to db dba
> db.b.find().count();
5562
--分片2
[root@pc ~]# mongo localhost:1003
MongoDB shell version: 2.6.9
connecting to: localhost:1003/test
> show dbs;
admin (empty)
dba 0.078GB
local 0.078GB
> use dba;
switched to db dba
> show tables;
b
system.indexes
> db.b.find().count();
94438
--本篇文章参考自:搭建mongodb分片,MongoDB分片实战(二):Sharding,Mongodb权威指南。