在实际生产环境中,我们往往需要对数据进行分片,以满足业务的需求,本文将介绍如何使用Docker部署MongoDB分片+副本集集群。
本次实践部署mongodb集群,
主要借鉴于该博客(https://blog.csdn.net/weixin_42104521/article/details/103731266)。
一、原理简析
Mongodb一共有三种集群搭建的方式:
Replica Set(副本集)、
Sharding(切片)
Master-Slaver(主从)
mongoDB目前已不推荐使用主从模式,取而代之的是副本集模式。副本集其实一种互为主从的关系,可理解为主主。
副本集:指将数据复制,多份保存,不同服务器保存同一份数据,在出现故障时自动切换。对应的是数据冗余、备份、镜像、读写分离、高可用性等关键词;
分片:则指为处理大量数据,将数据分开存储,不同服务器保存不同的数据,它们的数据总和即为整个数据集。追求的是高性能。
本实验模拟的MongoDB集群分以下几个层次或角色
1 2 3 4 5 6 7 8 9 10
| mongos层:请求的入口,是router的角色,相当于监听,负责将请求分发到对应的存储数据的shard上,多副本冗余
config server层:记录了mongos中使用到的元数据,自动向mongos同步最新的集群配置,多副本冗余
shard主节点层:将数据分片,数据库拆分,并将其分散在不同的机器上,原理是将整个数据集合切块 块分散到各个shard中,每个shard只负责总数据的一部分,通过一个均衡器来对各个shard均衡,多副本冗余
shard副本层:是shard的备份,多副本冗余
shard仲裁层:用于仲裁,不存储数据,使用最小的资源,需要基数个仲裁角色,且不能放在同一设备上
|
主机角色端口规划
本次实践在自建虚拟机进行部署,三台主机,各分配一个IP地址,IP地址如下:
| 服务器 |
192.168.1.32 |
192.168.1.33 |
192.168.1.35 |
| 服务端口 |
mongos:27017 |
mongos:27017 |
mongos:27017 |
| 服务端口 |
config server:9001 |
config server:9001 |
config server:9001 |
| 服务端口 |
shard1 主节点:9005 |
shard1 副节点:9005 |
shard1 仲裁节点:9005 |
| 服务端口 |
shard2 仲裁节点:9006 |
shard2 主节点:9006 |
shard2 副节点:9006 |
| 服务端口 |
shard3 副节点:9007 |
shard3 仲裁节点:9007 |
shard3 主节点:9007 |
可以看到每台主机上有1个mongos、1个config server、3个分片,三台主机的相同分片之间构成了主、副和仲裁三个角色。
总结
1 2 3 4 5
| 应用请求mongos来操作mongodb的增删改查 配置服务器存储数据库元信息,并且和mongos做同步 数据最终存入在shard(分片)上 为了防止数据丢失同步在副本集中存储了一份 仲裁在数据存储到分片的时候决定存储到哪个节点
|
二、部署配置服务器
创建挂载目录、配置文件
1 2
| mkdir /data/mongod/configdata/configsvr -p //三台主机都执行 mkdir /data/mongod/conf/{configsvr,keyfile} -p // keyfile在开启用户认证时需要
|
配置文件
1 2 3 4 5 6 7 8
| net: bindIpAll: true replication: replSetName: rs_configsvr sharding: clusterRole: configsvr
|
启动configsvr
1 2 3 4 5 6 7
| docker run -d -p 9001:27019 --name configsvr \ --entrypoint "mongod" \ -v /data/mongod/configdata/configsvr:/data/configdb \ -v /data/mongod/conf/keyfile:/data/keyfile \ -v /data/mongod/conf/configsvr:/data/conf \ mongo:4.0.21 -f /data/conf/mongod.conf
|
备注:如果docker ps 没有刚才创建的容器名称,可以使用docker logs <容器id>查看docker 日志
初始化配置服务复制集
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| docker exec -it configsvr bash
mongo --host 192.168.1.32 --port 9001
use admin rs.initiate({ _id: "rs_configsvr", configsvr: true, members: [ { _id : 0, host : "192.168.1.32:9001" }, { _id : 1, host : "192.168.1.33:9001" }, { _id : 2, host : "192.168.1.35:9001" } ] } )
rs.status() //查看状态
|
三、创建分片副本集
创建分片副本集配置文件、挂载文件
1 2 3 4 5 6 7 8
| mkdir /data/mongod/shard1/{log,db} -p mkdir /data/mongod/shard2/{log,db} -p mkdir /data/mongod/shard3/{log,db} -p chmod -R 777 /data/mongod/shard1 chmod -R 777 /data/mongod/shard2 chmod -R 777 /data/mongod/shard3 mkdir -p /data/mongod/conf/{shard1,shard2,shard3}
|
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
|
storage: dbPath: /home/mongod/db journal: enabled: true directoryPerDB: true
systemLog: destination: file logAppend: true path: /home/mongod/log/mongod.log
net: bindIpAll: true
setParameter: enableLocalhostAuthBypass: false
replication: replSetName: rs_shardsvr1 sharding: clusterRole: shardsvr
|
注意事项:
1、需要提前建立需要的文件夹。并赋予权限(chmod -R 750 文件夹)。
2、三个分片服务器建立在三个位置,(docker代码 -v 参数即为实际建立需要的文件夹),需要注意对应创建分片配置文件,文件内容一致。
3、注意配置文件中的数据库文件报错路径以及日志文件路径,按需更改。
4、分片服务端口需要映射 27018
shard1 分片
1、mongod分片部署
1 2 3 4 5 6 7
| docker run --name shardsvr1 -d -p 9005:27018 \ --entrypoint "mongod" \ -v /data/mongod/shard1:/home/mongod \ -v /data/mongod/conf/keyfile/:/data/keyfile/ \ -v /data/mongod/conf/shard1/:/data/conf/ \ mongo:4.0.21 -f /data/conf/mongod.conf
|
2、初始化分片服务器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| docker exec -it shardsvr1 bash
mongo --host 192.168.1.32 --port 9005 use admin rs.initiate( { _id : "rs_shardsvr1", members: [ { _id : 0, host : "192.168.1.32:9005",priority:5 }, { _id : 1, host : "192.168.1.33:9005",priority:3 }, { _id : 2, host : "192.168.1.35:9005",arbiterOnly:true } ] } )
|
shard2 分片
1、mongod分片部署
1 2 3 4 5 6 7
| docker run --name shardsvr2 -d -p 9006:27018 \ --entrypoint "mongod" \ -v /data/mongod/shard2:/home/mongod \ -v /data/mongod/conf/keyfile/:/data/keyfile/ \ -v /data/mongod/conf/shard2/:/data/conf/ \ mongo:4.0.21 -f /data/conf/mongod.conf
|
2、初始化分片服务器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| docker exec -it shardsvr2 bash
mongo --host 192.168.1.33 --port 9006 use admin rs.initiate( { _id : "rs_shardsvr2", members: [ { _id : 0, host : "192.168.1.32:9006",arbiterOnly:true }, { _id : 1, host : "192.168.1.33:9006",priority:5 }, { _id : 2, host : "192.168.1.35:9006",priority:3 } ] } )
|
shard3 分片
1、mongod分片部署
1 2 3 4 5 6 7
| docker run --name shardsvr3 -d -p 9007:27018 \ --entrypoint "mongod" \ -v /data/mongod/shard3:/home/mongod \ -v /data/mongod/conf/keyfile/:/data/keyfile/ \ -v /data/mongod/conf/shard3/:/data/conf/ \ mongo:4.0.21 -f /data/conf/mongod.conf
|
2、初始化分片服务器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| docker exec -it shardsvr3 bash
mongo --host 192.168.1.35 --port 9007 // 尽量在主节点执行,否则可能会出现报错 use admin rs.initiate( { _id : "rs_shardsvr3", members: [ { _id : 0, host : "192.168.1.32:9007",priority:3 }, { _id : 1, host : "192.168.1.33:9007",arbiterOnly:true }, { _id : 2, host : "192.168.1.35:9007",priority:5 } ] } )
|
四,创建mongos,连接mongos到分片集群
创建mongos配置文件
1 2 3 4 5 6 7 8 9 10
| mkdir /data/mongod/conf/mongos -p //三台主机都执行
vim /data/mongod/conf/mongos/mongod.conf
net: bindIpAll: true
sharding: configDB: rs_configsvr/192.168.1.32:9001,192.168.1.33:9001,192.168.1.35:9001
|
mongos 部署
1、分片路由部署,三台均执行相同操作
1 2 3 4 5 6
| docker run --name mongos -d \ -p 27017:27017 \ --entrypoint "mongos" \ -v /data/mongod/conf/keyfile/:/data/keyfile/ \ -v /data/mongod/conf/mongos/:/data/conf/ \ mongo:4.0.21 -f /data/conf/mongod.conf
|
备注:
rs_configsvr/192.168.1.32:9001,192.168.1.33:9001,192.168.1.35:9001: 配置服务名称/配置服务端口(多个用逗号分隔)
2、初始化mongos
1 2 3 4 5 6 7 8 9 10 11 12
| docker exec -it mongos bash
mongo --host 127.0.0.1 --port 27017 use admin
sh.addShard("rs_shardsvr1/192.168.1.32:9005,192.168.1.33:9005,192.168.1.35:9005") sh.addShard("rs_shardsvr2/192.168.1.32:9006,192.168.1.33:9006,192.168.1.35:9006") sh.addShard("rs_shardsvr3/192.168.1.32:9007,192.168.1.33:9007,192.168.1.35:9007")
sh.status() //查看状态
|
开启分片功能
1 2 3 4 5 6 7 8 9 10 11
| 虽然数据库采用分片集群的方式部署,但如果db和collection不启用分片的话(默认是不启用的),数据不会分片存储,此时如果向集群中导入一个db,会将整个db随机存储到任意一个分片中,而不是拆分存储到多个分片。 db启用分片: sh.enableSharding("库名") sh.enableSharding("<database>") 将上述命令中的“”换成实际的db名。
collection启用分片: sh.shardCollection("库名.集合名",{"key":1}) sh.shardCollection("<database>.<collection>", { <shard key> : "hashed" } ) 上述命令中的“< database >.< collection >”为实际的db名和collection名;“{ < shard key > : “hashed” }”为片键的集合。
|
五,测试使用
测试使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
docker exec -it mongos bash
mongo --host 127.0.0.1 --port 27017 use admin
db.runCommand( { enablesharding : "testdb1"}); db.runCommand( { shardcollection : "testdb1.tab1",key : {id: 1} } )
use testdb1; for(var i=1;i<=20000;i++) db.tab1.save({id:i,"test1":"testval1"});
db.tab1.stats(); exit
|
分别在三个主机上操作配置库、插入测试数据、查看测试数据
验证了副本同步,最后的显示结果看到 “sharded” : true 表示分片也是成功的
六、开启登录认证
设置数据库账号
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| 在任意mongos节点操作
docker exec -it mongos bash
mongo --host 127.0.0.1 --port 27017 mongos> use admin switched to db admin mongos> show collections
添加两个管理员账号,一个系统管理员:system 一个数据库管理员:administrator #先添加系统管理员账号,用来管理用户 mongos> db.createUser({user:"system",pwd:"123456",roles:[{role:"root",db:"admin"}]})
mongos> db.createUser({user:'administrator', pwd:'123456', roles:[{ role: mongos> db.auth('administrator','123456') //添加管理员用户认证,认证之后才能管理所有数据库
mongo 192.168.1.33:27017 -u system -p 123456 --authenticationDatabase admin mongo 192.168.1.35:27017 -u administrator -p 123456 --authenticationDatabase admin
|
开启登录验证
1 2 3 4 5 6 7 8 9 10
| mkdir /data/mongod/conf/keyfile -p //三台主机都执行
cd /data/mongod/conf/keyfile //切换到指定目录 openssl rand -base64 756 > key.file //创建一个 keyfile(使用 openssl 生成 756 位 base64 加密的字符串) chmod 600 ./key.file
scp ./key.file root@192.168.1.33:/data/mongod/conf/keyfile scp ./key.file root@192.168.1.33:/data/mongod/conf/keyfile
|
设置配置文件
1 2 3 4 5 6 7 8 9
| 使用访问控制强制重新启动复制集的每个成员
security: keyFile: /data/keyfile/key.file authorization: enabled
security: keyFile: /data/keyfile/key.file
|
重启集群
1 2
| docker ps |grep mongo |awk -F " " '{print $1}' |xargs -r docker restart
|