前言
本文将通过3台虚拟机来搭建一个分片集群【具体分片集群概念可参考前面文章】。最终搭建完成后的样子如下:
192.168.40.128【虚拟机1】 | 192.168.40.129【虚拟机2】 | 192.168.40.130【虚拟机3】 | 副本集 |
shard1 master:27017 | shard1 secondary:27017 | shard1 arbiter:27017 | shard1_rs |
shard2 arbiter:27018 | shard2 master:27018 | shard2 secondary:27018 | shard2_rs |
shard3 secondary:27019 | shard3 arbiter:27019 | shard3 master:27019 | shard3_rs |
mongos:30000 | mongos:30000 (可有可无) | mongos:30000 (可有可无) | |
shard config server:30001 | shard config server:30001 (可有可无) | shard config server:30001 (可有可无) |
如果上图看着有点晕,没关系,跟着下面的做,做完了再回头看。
分片集群必须的三个主要组件,配置分片集群实际就是配置并运行这三个组件
- Shard:
- Config Server:
- mongos:
步骤
第一步:在三台虚拟机上的/usr/local/目录下分别建立如下内容,在后面搭建时配置文件中需要用到这些文件和文件夹:
mongodb
|--data
| |--mongos
| |--shard1
| |--shard2
| |--shard3
| |--shard_config_server
|-- log
|-- pid
| --shard1.conf
| --shard2.conf
| --shard3.conf
| --shard_config_server.conf
以上内容有扩展名的是文件,没扩展名的是文件夹,所有的conf都可以先拷贝mongodb默认mongodb.conf,然后在改名即可。
第二步:创建Config Server副本集【Mongodb3.4以后Config Server必须是副本集】
- 将下面内容复制并覆盖到三台虚拟机上的shard_config_server.conf中:
# mongod.conf # where to write logging data. systemLog: destination: file logAppend: true path: /usr/local/mongodb/log/shard_config_server.log #第一步创建的log文件夹 # Where and how to store data. storage: dbPath: /usr/local/mongodb/data/shard_config_server #第一步创建的文件夹 journal: enabled: true # engine: # wiredTiger: # how the process runs processManagement: fork: true # fork and run in background pidFilePath: /usr/local/mongodb/pid/shard_config_server.pid #第一步创建的文件夹 timeZoneInfo: /usr/share/zoneinfo #默认,无需修改 # network interfaces net: port: 30001 bindIp: 0.0.0.0 #security: #operationProfiling: replication: replSetName: shard_config_server_rs #因为必须搭建副本集,所以这里要设置 sharding: clusterRole: configsvr #因为要配置分片,所以这里也要设置,固定写法 ## Enterprise-Only Options #auditLog: #snmp:
- 在三台虚拟机上分别运行下面命令,启动Server Config
# 路径是第一步创建的文件路径 mongod -f /usr/local/mongodb/shard_config_server.conf
- 通过初始化命令,将三个虚拟机上的Server Config组成副本集
这一步在其中一个虚拟机上执行一次就行,不要三个虚拟机都执行。切记!# 第一步:先通过mongosh连接上任意一个刚才启动的Config Server mongosh --port 30001 #一定要指定端口,否则默认用27017端口 # 第二步:初始化,组成副本集,别忘了先关闭防火墙 rs.initiate( { _id : "shard_config_server_rs", members: [ { _id: 0, host: "192.168.40.128:30001" }, { _id: 1, host: "192.168.40.129:30001" }, { _id: 2, host: "192.168.40.130:30001" } ] })
初始化成功后,命令行就会变成如下样子
开头会显示出副本集的名字,就是配置文件中配置的replSetName的值
第三步:创建shard
所谓创建shard,就是创建mongod实例,然后用来保存分片后的某一部分数据。
- 分别在三个虚拟机上复制如下内容到配置文件shard1.conf
# mongod.conf # where to write logging data. systemLog: destination: file logAppend: true path: /usr/local/mongodb/log/shard1.log # Where and how to store data. storage: dbPath: /usr/local/mongodb/data/shard1 journal: enabled: true # engine: # wiredTiger: # how the process runs processManagement: fork: true # fork and run in background pidFilePath: /usr/local/mongodb/pid/shard1.pid # location of pidfile timeZoneInfo: /usr/share/zoneinfo # network interfaces net: port: 27017 bindIp: 0.0.0.0 # Enter 0.0.0.0,:: to bind to all IPv4 and IPv6 addresses or, alternatively, use the net.bindIpAll setting. #security: #operationProfiling: replication: replSetName: shard1_rs # 因为也要通过三个虚拟机组成副本集,所以需要设置副本集名称 sharding: clusterRole: shardsvr # 因为是保存分片数据,所以要设置这个属性 ## Enterprise-Only Options #auditLog: #snmp:
-
分别在三个虚拟机上复制如下内容到配置文件shard2.conf
# mongod.conf # for documentation of all options, see: # http://docs.mongodb.org/manual/reference/configuration-options/ # where to write logging data. systemLog: destination: file logAppend: true path: /usr/local/mongodb/log/shard2.log # Where and how to store data. storage: dbPath: /usr/local/mongodb/data/shard2 journal: enabled: true # engine: # wiredTiger: # how the process runs processManagement: fork: true # fork and run in background pidFilePath: /usr/local/mongodb/pid/shard2.pid # location of pidfile timeZoneInfo: /usr/share/zoneinfo # network interfaces net: port: 27018 bindIp: 0.0.0.0 # Enter 0.0.0.0,:: to bind to all IPv4 and IPv6 addresses or, alternatively, use the net.bindIpAll setting. #security: #operationProfiling: replication: replSetName: shard2_rs sharding: clusterRole: shardsvr ## Enterprise-Only Options #auditLog: #snmp:
-
分别在三个虚拟机上复制如下内容到配置文件shard3.conf
# mongod.conf # for documentation of all options, see: # http://docs.mongodb.org/manual/reference/configuration-options/ # where to write logging data. systemLog: destination: file logAppend: true path: /usr/local/mongodb/log/shard3.log # Where and how to store data. storage: dbPath: /usr/local/mongodb/data/shard3 journal: enabled: true # engine: # wiredTiger: # how the process runs processManagement: fork: true # fork and run in background pidFilePath: /usr/local/mongodb/pid/shard3.pid # location of pidfile timeZoneInfo: /usr/share/zoneinfo # network interfaces net: port: 27019 bindIp: 0.0.0.0 # Enter 0.0.0.0,:: to bind to all IPv4 and IPv6 addresses or, alternatively, use the net.bindIpAll setting. #security: #operationProfiling: replication: replSetName: shard3_rs sharding: clusterRole: shardsvr ## Enterprise-Only Options #auditLog: #snmp:
-
将如下3个命令在每个虚拟机上都执行一次,目的是在每个虚拟机上都创建shard1,shard2,shard3三个shard
这一步执行完后,三个虚拟机会同时存在shard1,shard2,shard3(看开头的表格),然后下面会将3个虚拟机上的shard1组成一个副本集,shard2组成一个副本集,shard3组成一个副本集。# 第一步创建的配置文件的路径 mongod -f /usr/local/mongodb/shard1.conf mongod -f /usr/local/mongodb/shard2.conf mongod -f /usr/local/mongodb/shard3.conf
- 在三个虚拟机中随便找一个,然后分别执行下面3段命令,将3个shard1组成副本集,3个shard2组成副本集,3个shard3组成副本集
通过初始化,将三个shard1的分片组成副本集,命令如下:
#第一步:通过mongosh连接上mongod mongosh --port 27017 #第二步:初始化,组成副本集 rs.initiate( { _id : "shard1_rs", members: [ { _id: 0, host: "192.168.40.128:27017" }, { _id: 1, host: "192.168.40.129:27017" }, { _id: 2, host: "192.168.40.130:27017" } ]})
将三个shard2的分片组成副本集
#第一步:通过mongosh连接上mongod mongosh --port 27018 #第二步:初始化,组成副本集 rs.initiate( { _id : "shard2_rs", members: [ { _id: 0, host: "192.168.40.128:27018" }, { _id: 1, host: "192.168.40.129:27018" }, { _id: 2, host: "192.168.40.130:27018" } ]})
将三个shard3的分片通过初始化组成副本集
#第一步:通过mongosh连接上mongod mongosh --port 27019 #第二步:初始化,组成副本集 rs.initiate( { _id : "shard3_rs", members: [ { _id: 0, host: "192.168.40.128:27019" }, { _id: 1, host: "192.168.40.129:27019" }, { _id: 2, host: "192.168.40.130:27019" } ]})
第四步:创建mongos
mongos作为一个路由的角色,我们要操作上面创建的shard1,shard2,shard3分片集群中的数据时,都要通过mongos为入口来进行操作。
mongos既可以启动一个,也可以跟上面Config Server或者shard一样创建副本集的形式,这里我们就不创建副本集了,我们只运行一个mongos,所以本步中所有的操作都只在【虚拟机1】中操作
- 复制下面配置信息到【虚拟机1】的mongos.conf文件中
# mongod.conf # for documentation of all options, see: # http://docs.mongodb.org/manual/reference/configuration-options/ # where to write logging data. systemLog: destination: file logAppend: true path: /usr/local/mongodb/log/mongos.log # Where and how to store data. # engine: # wiredTiger: # how the process runs processManagement: fork: true # fork and run in background pidFilePath: /usr/local/mongodb/pid/mongos.pid # location of pidfile timeZoneInfo: /usr/share/zoneinfo # network interfaces net: port: 30000 bindIp: 0.0.0.0 #security: #operationProfiling: #replication: # replSetName: "rs0" #这个属性就是用来设置路由的,不能忽略 sharding: configDB: shard_config_server_rs/192.168.40.128:30001,192.168.40.129:30001,192.168.40.130:30001 #shard_config_server_rs就是我们Config Server副本集的名字,就是shard_config_server.conf中replSetName的值 ## Enterprise-Only Options #auditLog: #snmp:
注意:
因为mongos主要用来作为路由使用,所以不需要配置dbpath,只需要配置log的path就行了,所以我把storage属性都删除了。否则会报错误【Unrecognized option: storage.dbPath】。另外因为他的作用是路由,所以配置中还需要设定configDB这个属性来指定Config Server副本集的地址和端口。 -
启动mongos
mongod -f /usr/local/mongodb/mongos.conf
-
通过mongosh连接到启动的mongos上,如下图:
-
添加shard到cluster中,分别执行下面三条指令:
上边通过mongosh连接到mongos后,执行下面3条指令,将之前创建的shard1,shard2,shard3的副本集机器的地址和端口配置到mongos中#shard1_rs,shard2_rs,shard3_rs就是我们前面配置文件中配置的shard副本集中的replSetName的值 sh.addShard( "shard1_rs/192.168.40.128:27017,192.168.40.129:27017,192.168.40.130:27017") sh.addShard( "shard2_rs/192.168.40.128:27018,192.168.40.129:27018,192.168.40.130:27018") sh.addShard( "shard3_rs/192.168.40.128:27019,192.168.40.129:27019,192.168.40.130:27019")
添加成功后如下图:
此时分片集群就搭建完成了,现在可以通过命令查看一些相关信息,如下:
如果想查看当前分片的副本集有哪些,可执行下面命令:如果想查看分片副本集的状态,可执行如下命令:
===========到此为止,配置就完成了,下面开始使用分片========================
第五步:使用分片集群
前面四步是搭建分片集群,那么如何使用和验证搭建好的分片集群,就在这一步来交给大家
现在开始的操作都是在连接到mongos的那个mongosh客户端上操作。
- 开启分片功能(想让哪个数据库有分片的功能,就开启那个数据库)
sh.enableSharding("db_shard_test") #db_shard_test就是要开启分片的数据库名字
我们这里指定让db_shard_test这个数据库开启shard功能,此时这个数据库还没创建也没关系 - 指定哪些数据库中的表可以进行分片
sh.shardCollection("db_shard_test.tb1", { userId: 1} ) # tb1是表,userId是表中的一个字段,用这个字段来作为分片索引,如果此时tb1中还没记录,那么这里会自动将userId作为索引,如果表中已经有数据,需要先手动去把userId这个字段设置为索引
执行这一步之前,必须先执行上面【1】的开启分片。
另外如果在进行sharding前,你的Colloection已经有数据了,那么必须先创建索引,然后才能进行这一步操作
- 添加测试数据
要触发分片,必须要让数据到达一定的数据量才行,否则数据不会进行分片,所以先添加数据
添加之前,先看一下现在数据库中数据的大小
可以看到现在数据12.3KB,这么小的数据,肯定不会进行分片的,必须数据量很大时,才是触发分片功能,所以下面我们进行数据添加,方法如下:#以下[1][2][3]分别执行 # [1]切换数据库到db_shard_test use db_shard_test # [2] 创建数据 var arr=[]; for(var i=0;i<2000000;i++){ # 建议每次添加100000条,这样一次添加2000000容易内容溢出 var uid = i; var name = "name" +i ; arr.push({"name":name,"userId":uid}); } # [3] 添加数据到数据库中 db.tb1.insertMany(arr);
然后就等待数据的插入执行,当出现下图时,表示执行完成了
大约数据库数据容量达到170兆时,就触发了分片,如下:
然后通过sh.status(),来看是否进行分片,如下图,显示已经进行了分片:
从图可以看出userId的1到1974924这些记录在shard2_rs里面存着,userId的 1974924到最后这些数据在shard3_rs上存着。如果红框中只有一行,那么就说明还没有进行分片来保存数据。
上面是从命令来观察是否进行了分片,并且从命令返回的数据可以看出分片后的数据都放在哪个虚拟机对应的mongodb中,下面我们就来看一下:
首先,那么我们就随便找一个虚拟机,到shard1_rs中观察数据库,命令为:mongosh --port 27017,如下:
然后,通过命令mongsh --port 27019,连接到shard2_rs中,如下:
然后,我们在去shard3_rs中看是否也有数据,命令为:mongsh --port 27019
通过上面3个图可以看出,数据真的进行了分片,放到了不同的mongodb数据库中,而不是都放在一个mongodb数据库中了,3个图中的db_shard_test的数据和正好170兆,跟我们在mongos中看到的数据量是相同的。
mongosh连接到的mongos中看到的是数据的总和,而在每个保存分片的副本集上看到的是分片数据,也就是数据分解后的一部分数据。每部分数据加起来就正好等于mongos上看到的
==================到此,分片的配置和测试就结束了==================