MongoDB在单节点中也可以做复制集,但是仅限于测试实验,最大的好处就是部署方便快速,可以随便添加新节点,节省资源。在这里我使用的是MongoDB 3.2版本进行复制集实验(但MongoDB配置文件使用的是老版本格式)。
一、实验环境
1)节点信息:192.168.60.10
2)节点确保iptables和selinux已关闭
1 2 |
[root@localhost ~]# iptables -F [root@localhost ~]# setenforce 0 |
3)实验环境图
上图就是我的实验环境图。而在生产环境中,mongos节点最少是两个或是更多节点,Config Server节点做成一个复制集,而Shard节点则更应该是复制集已保证数据的安全性。所以就可以考虑在使用资源最少的情况下从而部署可靠的分片集群,如下示意图。
二、安装MongoDB 3.2
1 2 3 4 5 |
mongodb-org-3.2.0-1.el6.x86_64.rpm mongodb-org-mongos-3.2.0-1.el6.x86_64.rpm mongodb-org-server-3.2.0-1.el6.x86_64.rpm mongodb-org-shell-3.2.0-1.el6.x86_64.rpm mongodb-org-tools-3.2.0-1.el6.x86_64.rpm |
PS:需要的软件包可以去https://repo.mongodb.org/yum/redhat/下载,MongoDB的安装很简单,怎么安装都成。
三、配置集群
1)创建所需要的目录
1 2 3 4 5 |
[root@localhost ~]# mkdir -p /mongodb/{conf,log,pid,data} [root@localhost ~]# mkdir -p /mongodb/conf/{conf27017,conf27018,conf27028,conf27019} [root@localhost ~]# mkdir -p /mongodb/log/{log27017,log27018,log27028,log27019} [root@localhost ~]# mkdir -p /mongodb/pid/{pid27017,pid27018,pid27028,pid27019} [root@localhost ~]# mkdir -p /mongodb/data/{data27017,data27018,data27028,data27019} |
2)创建每个节点需要的配置文件及参数
Shard节点(192.168.60.10:27018)
一个shard节点可以是一个单独的mongod或者是一个replica set。在生产环境中,每个分片都应该是一个复制集。Shard进程的默认端口就是27018。参见部署复制集将每个分片部署为复制集。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
[root@localhost ~]# cat /mongodb/conf/conf27018/mongod.conf ###Base configure # 日志文件; logpath = /mongodb/log/log27018/mongod.log # 日志追加; logappend = true #数据目录; dbpath = /mongodb/data/data27018 # 实例端口; port = 27018 # 监听地址; bind_ip=192.168.60.10 # 守护进程模式开启; fork = true # 进程号文件; pidfilepath = /mongodb/pid/pid27018/mongod.pid # 日志轮询方式; logRotate = rename # 日志时间格式; timeStampFormat = ctime # 日志刷盘间隔(默认100秒) journalCommitInterval = 100 # 数据刷盘间隔(默认60秒) syncdelay = 60 # 最大连接数(默认65535) maxConns = 65536 ###Shard shardsvr = true |
PS:更多具体参数详细含义请看《MongoDB命令行选项介绍》
Shard节点(192.168.60.10:27028)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
[root@localhost ~]# cat /mongodb/conf/conf27028/mongod.conf ###Base configure logpath = /mongodb/log/log27028/mongod.log logappend = true dbpath = /mongodb/data/data27028 port = 27028 bind_ip=192.168.60.10 fork = true pidfilepath = /mongodb/pid/pid27028/mongod.pid logRotate = rename timeStampFormat = ctime journalCommitInterval = 100 syncdelay = 60 maxConns = 65536 ###Shard shardsvr = true |
Config Server节点(192.168.60.10:27019)
配置服务器必须开启1个(会有警告)或则3个,开启2个则会报错。Config server的默认端口就是27019。另外从MongoDB3.2开始,config servers可以部署为一个复制集,但这个复制集中的config server节点必须是WiredTiger存储引擎。
单节点Config Server
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
[root@localhost ~]# cat /mongodb/conf/conf27019/mongod.conf ###Base configure logpath = /mongodb/log/log27019/mongod.log logappend = true dbpath = /mongodb/data/data27019 port = 27019 bind_ip=192.168.60.10 fork = true pidfilepath = /mongodb/pid/pid27019/mongod.pid logRotate = rename timeStampFormat = ctime journalCommitInterval = 100 syncdelay = 60 maxConns = 65536 ###Config Server configsvr = true |
Mongos节点(192.168.60.10:27017)
mongos实例是轻量服务,并且不需要数据目录,所以只需要记录一下日志即可。你可以将 mongos 运行在已经部署了其他服务的系统中,比如应用服务器或者运行了mongod的机器上,mongos默认运行在 27017 端口上。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
[root@localhost ~]# cat /mongodb/conf/conf27017/mongod.conf ###Base configure logpath = /mongodb/log/log27017/mongod.log logappend = true port = 27017 bind_ip=192.168.60.10 fork = true pidfilepath = /mongodb/pid/pid27017/mongod.pid logRotate = rename timeStampFormat = ctime ###Mongos configdb = 192.168.60.10:27019 |
3)启动各节点
1 |
[root@localhost ~]# killall mongod |
Shard
1 2 3 4 5 6 7 8 |
[root@localhost ~]# mongod -f /mongodb/conf/conf27018/mongod.conf about to fork child process, waiting until server is ready for connections. forked process: 99669 child process started successfully, parent exiting [root@localhost ~]# mongod -f /mongodb/conf/conf27028/mongod.conf about to fork child process, waiting until server is ready for connections. forked process: 99239 child process started successfully, parent exiting |
Config Server
1 2 3 4 |
[root@localhost ~]# mongod -f /mongodb/conf/conf27019/mongod.conf about to fork child process, waiting until server is ready for connections. forked process: 99774 child process started successfully, parent exiting |
Mongos
1 2 3 4 5 |
[root@localhost ~]# mongos -f /mongodb/conf/conf27017/mongod.conf Mon Jan 18 04:06:07.495 W SHARDING [main] Running a sharded cluster with fewer than 3 config servers should only be done for testing purposes and is not recommended for production. about to fork child process, waiting until server is ready for connections. forked process: 99933 child process started successfully, parent exiting |
查看进程三个节点都启动了
1 2 3 4 5 |
[root@localhost ~]# ps aux | grep mongo root 99669 0.8 6.6 399360 66412 ? Sl 03:49 0:12 mongod -f /mongodb/conf/conf27018/mongod.conf root 99239 0.8 6.6 322350 56462 ? Sl 03:50 0:11 mongod -f /mongodb/conf/conf27028/mongod.conf root 99774 0.8 7.0 430904 70548 ? Sl 03:57 0:08 mongod -f /mongodb/conf/conf27019/mongod.conf root 99906 0.2 0.8 324108 8524 ? Sl 04:06 0:01 mongos -f /mongodb/conf/conf27017/mongod.conf |
4)向集群中添加分片
好了,到此为止MongoDB分片环境已经配置完毕了。接下来就是为这个集群添加分片了,大概步骤如下:
步骤一、连接到mongos
1 2 3 4 5 |
[root@localhost ~]# mongo 192.168.60.10:27017 MongoDB shell version: 3.2.0 connecting to: 192.168.60.10:27017/test mongos> mongos> |
步骤二、添加2个点节点Shard(必须在admin数据库下进行)
1 2 3 4 5 6 |
mongos> use admin switched to db admin mongos> sh.addShard( "192.168.60.10:27018") { "shardAdded" : "shard0000", "ok" : 1 } mongos> sh.addShard( "192.168.60.10:27028") { "shardAdded" : "shard0001", "ok" : 1 } |
步骤三、为集群数据库开启分片
1 2 3 4 |
mongos> show dbs config 0.000GB mongos> use shardtest switched to db shardtest |
在mongos节点上只有config默认数据库,上面创建了一个shardtest库,然后进入到admin数据库开启shardtest数据库分片。
1 2 3 |
mongos> use admin mongos> sh.enableSharding("shardtest") { "ok" : 1 } |
步骤四、对一个集合进行分片
1 2 3 |
mongos> use admin switched to db admin mongos> sh.shardCollection("shardtest.user",{userid:"hashed"}) |
这里对user集合创建一个片键,对userid字段进行创建片键(shard key)并使用哈希值做索引,保证数据的均衡。但注意的是这里的shardtest.user集合里面没有数据。
5)测试分片
使用db.user.stats()方法查看集合的状态信息,跟分片相关的会有这么几个参考值。
1. “sharded” : true
可以看出此集合是开启了分片的,如果值为false的话就表示未开启分片。
2. “shards”
标识这个集合有几个shard,然后每一个shard下面都会有很多参考信息,具体的就不说了。
使用sh.status()方法或db.printShardingStatus()命令查看分片状态信息。
下面在mongos节点上写了一个for循环往shardtest.user集合中插入100000条数据,看看是否平均分配存储到两个shard上面了。
1 2 3 4 5 6 7 8 |
mongos> use shardtest mongos> for(i=0;i<100000;i++)(db.user.insert({"userid":i})); WriteResult({ "nInserted" : 1 }) mongos> show dbs config 0.001GB shardtest 0.005GB mongos> db.user.count() 100000 |
然后登录到shard节点192.168.60.10:27018进行数据查看。
1 2 3 4 5 6 7 |
> show dbs local 0.000GB shardtest 0.002GB > use shardtest switched to db shardtest > db.user.count() 50393 |
然后登录到shard节点192.168.60.10:27028进行数据查看。
1 2 3 4 5 6 7 |
> show dbs local 0.000GB shardtest 0.002GB > use shardtest switched to db shardtest > db.user.count() 49607 |
由这两个节点可以看出,插入的100000条数据大致平均地分到了2个shard节点上了。如果此时再加入一个shard节点的话会怎么样呢?会进行数据块(chunk)迁移以保证均衡吗?下面我们再添加一个shard节点。
向集群中添加一个shard节点(192.168.60.10:27038)
1)创建并启动节点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
[root@localhost ~]# mkdir conf/conf27038/ [root@localhost ~]# mkdir data/data27038/ [root@localhost ~]# mkdir log/log27038 [root@localhost ~]# mkdir pid/pid27038 [root@localhost ~]# vi /mongodb/conf/conf27038/mongod.conf ###Base configure logpath = /mongodb/log/log27038/mongod.log logappend = true dbpath = /mongodb/data/data27038 port = 27038 bind_ip=192.168.60.10 fork = true pidfilepath = /mongodb/pid/pid27038/mongod.pid logRotate = rename timeStampFormat = ctime journalCommitInterval = 100 syncdelay = 60 maxConns = 65536 ###Shard shardsvr = true |
启动shard节点
1 2 3 4 |
[root@localhost ~]# mongod -f /mongodb/conf/conf27038/mongod.conf about to fork child process, waiting until server is ready for connections. forked process: 113036 child process started successfully, parent exiting |
2)然后在mongos节点中添加shard即可。
1 2 |
mongos> sh.addShard("192.168.60.10:27038") { "shardAdded" : "shard0002", "ok" : 1 } |
此时在用sh.status()查看分片的状态.
就会发现shards节点有了变化,且balancer:Currently running状态变为yes,进行数据块的迁移。当数据块迁移完成之后database:chunks显示的节点就会变成三个,如下,其数据分配比例是1:2:1。
1 2 3 4 |
chunks: shard0000 1 shard0001 2 shard0002 1 |
此时再看三个shard节点的数据分配情况,均衡器是根据数据块来进行迁移的,而默认数据块大小为64M,如下:
1 2 3 4 5 6 7 8 9 |
192.168.60.10:27018 > db.user.count() 25041 192.168.60.10:27028 > db.user.count() 49607 192.168.60.10:27038 > db.user.count() 25352 |
上面是使用哈希分片,如果100000条数据使用以范围为基础分片,那么3个Shard节点又会怎样存储数据呢?下面来看一看,测试时最好使用大数据量进行测试,我这数据量太小可能测不出很好的效果。
1)对一个集合进行分片
1 2 |
mongos> sh.shardCollection("shardtest.username",{userid:1}) { "collectionsharded" : "shardtest.username", "ok" : 1 } |
2)循环插入数据
1 |
mongos> for(i=0;i<100000;i++)(db.username.insert({"userid":i})); |
3)查看集群状态
1 2 3 4 5 6 7 8 9 |
mongos> sh.status() …………… chunks: shard0000 1 shard0001 1 shard0002 1 { "userid" : { "$minKey" : 1 } } -->> { "userid" : 1 } on : shard0001 Timestamp(2, 0) { "userid" : 1 } -->> { "userid" : 27 } on : shard0002 Timestamp(3, 0) { "userid" : 27 } -->> { "userid" : { "$maxKey" : 1 } } on : shard0000 Timestamp(3, 1) |
从这个状态可以看出,当一个集合内写入的数据达到可以分给多个shard的时候,这里用了100000条数据分别存储在shard0000、shard0001、shard0002这三个shard上。然后我们看下面对应的三条算法:
第一行、$minkey表示从最小的键到1的文档存储到shard0001.
第二行、表示从1到27的文档存储到shard00002上面.
第三行、表示从27到最后所有的文档存储在shard0000上面.
具体的数据分配方式暂时还不太清楚,等待后续补充。