本次实践部署mongodb集群,
主要借鉴于该博客(https://blog.csdn.net/weixin_42104521/article/details/103731266)。
Mongodb一共有三种集群搭建的方式:
Replica Set(副本集)、
Sharding(切片)
Master-Slaver(主从)
mongoDB目前已不推荐使用主从模式,取而代之的是副本集模式。副本集其实一种互为主从的关系,可理解为主主。
副本集:指将数据复制,多份保存,不同服务器保存同一份数据,在出现故障时自动切换。对应的是数据冗余、备份、镜像、读写分离、高可用性等关键词;
分片:则指为处理大量数据,将数据分开存储,不同服务器保存不同的数据,它们的数据总和即为整个数据集。追求的是高性能。
mongos层:请求的入口,是router的角色,相当于监听,负责将请求分发到对应的存储数据的shard上,多副本冗余
config server层:记录了mongos中使用到的元数据,自动向mongos同步最新的集群配置,多副本冗余
shard主节点层:将数据分片,数据库拆分,并将其分散在不同的机器上,原理是将整个数据集合切块
块分散到各个shard中,每个shard只负责总数据的一部分,通过一个均衡器来对各个shard均衡,多副本冗余
shard副本层:是shard的备份,多副本冗余
shard仲裁层:用于仲裁,不存储数据,使用最小的资源,需要基数个仲裁角色,且不能放在同一设备上
本次实践在自建虚拟机进行,有个别需求的同学,可以购买华为云ECS进行部署。 华为云-2核4G云主机低至487元/年(新用户1.5折起)
服务器 | 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个分片,三台主机的相同分片之间构成了主、副和仲裁三个角色。
应用请求mongos来操作mongodb的增删改查
配置服务器存储数据库元信息,并且和mongos做同步
数据最终存入在shard(分片)上
为了防止数据丢失同步在副本集中存储了一份
仲裁在数据存储到分片的时候决定存储到哪个节点
mkdir /data/mongod/configdata/configsvr -p //三台主机都执行
mkdir /data/mongod/conf/{configsvr,keyfile} -p // keyfile在开启用户认证时需要
# vim /data/mongod/conf/configsvr/mongod.conf
net:
bindIpAll: true
replication:
replSetName: rs_configsvr # 副本集名称,相同副本须使用同一个副本集名称
sharding:
clusterRole: configsvr # 定义为mongo配置服务器
## 三台主机均执行此操作
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 日志
# 进入容器中,创建的三个配置服务中随便一个
docker exec -it configsvr bash
# 登录mongo
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() //查看状态
## 创建配置文件、数据目录
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}
## 三台主机均创建三个配置文件,shard分片名不同即可
#所有用到的文件夹和文件必须在创建的时候给权限,包括重新创建,也需要重新给权限,并且文件夹要提前创建好
# vim /data/mongod/conf/{shard1,shard2,shard3}/mongod.conf //添加如下配置信息,分片服务名称不一致即可
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
## 三台主机(192.168.1.32、33、35)执行如下启动命令
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
# 登录进容器中,任意一台
docker exec -it shardsvr1 bash
# 登录分片服务器
# 192.168.1.32 主分片节点
# 192.168.1.33 副分片节点
# 192.168.1.35 仲裁分片节点,arbiterOnly:true 表示为仲裁节点
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 }
]
}
)
#rs.status() 查看状态
## 三台主机(192.168.1.32、33、35)执行如下启动命令
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
# 登录进容器中,尽量在主节点执行,否则会报错
docker exec -it shardsvr2 bash
#登录分片服务器
# 192.168.1.32 仲裁分片节点
# 192.168.1.33 主分片节点
# 192.168.1.35 副分片节点
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 }
]
}
)
#rs.status() 查看状态
## 三台主机(192.168.1.32、33、35)执行如下启动命令
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
# 登录进容器中,任意节点
docker exec -it shardsvr3 bash
# 登录分片服务器
# 192.168.1.32 副分片节点
# 192.168.1.33 仲裁分片节点
# 192.168.1.35 主分片节点
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 }
]
}
)
#rs.status() 查看状态
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配置服务器
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: 配置服务名称/配置服务端口(多个用逗号分隔)
# 进入mongos 容器中
docker exec -it mongos bash
# 连接mongos
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() //查看状态
## db和collection开启分片功能
虽然数据库采用分片集群的方式部署,但如果db和collection不启用分片的话(默认是不启用的),数据不会分片存储,此时如果向集群中导入一个db,会将整个db随机存储到任意一个分片中,而不是拆分存储到多个分片。
db启用分片:
sh.enableSharding("库名")
sh.enableSharding("" )
将上述命令中的“”换成实际的db名。
collection启用分片:
sh.shardCollection("库名.集合名",{"key":1})
sh.shardCollection("." , { <shard key> : "hashed" } )
上述命令中的“< database >.< collection >”为实际的db名和collection名;“{ < shard key > : “hashed” }”为片键的集合。
# 任意一节点操作
# 进入mongos 容器中
docker exec -it mongos bash
# 连接mongos
mongo --host 127.0.0.1 --port 27017
use admin
# testdb1开启分片功能
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
# 使用testdb1库
# 循环插入数据到testdb1库的tab1集合中的键id中
# 该库对应的该集合对应的该键被设置成了分片
# 查看分片情况
分别在三个主机上操作配置库、插入测试数据、查看测试数据
验证了副本同步,最后的显示结果看到 “sharded” : true 表示分片也是成功的
在任意mongos节点操作
# 进入mongos 容器中
docker exec -it mongos bash
# 连接mongos
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
mkdir /data/mongod/conf/keyfile -p //三台主机都执行
# 在192.168.1.32节点服务器上操作
cd /data/mongod/conf/keyfile //切换到指定目录
openssl rand -base64 756 > key.file //创建一个 keyfile(使用 openssl 生成 756 位 base64 加密的字符串)
chmod 600 ./key.file
# 复制文件到其他主机
scp ./key.file [email protected]:/data/mongod/conf/keyfile
scp ./key.file [email protected]:/data/mongod/conf/keyfile
使用访问控制强制重新启动复制集的每个成员
# 依次在每台机器上的mongod(注意是所有的mongod不是mongos)的配置文件中加入下面一段配置。如我在192.168.1.32上的config server,shard1,shard2,shard3都加入下面的配置文件
security:
keyFile: /data/keyfile/key.file
authorization: enabled
# 依次在每台机器上的mongos配置文件中加入下面一段配置
security:
keyFile: /data/keyfile/key.file
# 在三台主机执行如下命令
docker ps |grep mongo |awk -F " " '{print $1}' |xargs -r docker restart