Docker部署MongoDB分片+副本集集群(实战)

引言

本次实践部署mongodb集群,
主要借鉴于该博客(https://blog.csdn.net/weixin_42104521/article/details/103731266)。

一、原理简析

Mongodb一共有三种集群搭建的方式:
Replica Set(副本集)、
Sharding(切片)
Master-Slaver(主从)

      mongoDB目前已不推荐使用主从模式,取而代之的是副本集模式。副本集其实一种互为主从的关系,可理解为主主。
      副本集:指将数据复制,多份保存,不同服务器保存同一份数据,在出现故障时自动切换。对应的是数据冗余、备份、镜像、读写分离、高可用性等关键词;
      分片:则指为处理大量数据,将数据分开存储,不同服务器保存不同的数据,它们的数据总和即为整个数据集。追求的是高性能。

本实验模拟的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配置服务器

启动configsvr

## 三台主机均执行此操作
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

shard1 分片

1、mongod分片部署

## 三台主机(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

2、初始化分片服务器

# 登录进容器中,任意一台
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() 查看状态

shard2 分片

1、mongod分片部署

## 三台主机(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

2、初始化分片服务器

# 登录进容器中,尽量在主节点执行,否则会报错
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() 查看状态

shard3 分片

1、mongod分片部署

## 三台主机(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

2、初始化分片服务器

# 登录进容器中,任意节点
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() 查看状态

四,创建mongos,连接mongos到分片集群

创建mongos配置文件

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配置服务器

mongos 部署

1、分片路由部署,三台均执行相同操作

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

# 进入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

你可能感兴趣的:(部署,运维)