龙蜥8部署mongodb7分片集群
环境描述:
Anolis OS release 8.6
mongodb-org-7.0.9-1
服务器规划:
主机名 | IP地址 | Mongos Server组件端口 | Config Server组件端口 | Shard Server组件端口 |
mongodb01 | 192.168.109.137 | 27017 | 27018 |
主节点:27019 副本节点:27020 仲裁节点:27021 |
mongodb02 | 192.168.109.138 | 27017 | 27018 |
仲裁节点:27019 主节点:27020 副本节点:27021 |
mongodb03 | 192.168.109.139 | 27017 | 27018 |
副本节点:27019 仲裁节点:27020 主节点:27021 |
结构图:
各组件功能说明:
数据库集群请求的入口,所有请求都通过mongos server进行协调,不需在应用程序添加路由选择器,mongos server自己就是一个请求分发中心,它负责把数据请求请求转发到对应的shard服务器上。
在生产环境通常需要设置多mongos server作为请求入口,防止其中一个挂掉所有的mongodb请求都没法操作
配置服务器,存储所有数据库元信息(路由、分片)的配置。
mongos server本身没有物理存储分片服务器和数据路由信息,只是缓存在内存里,配置服务器则实际存储这些数据。
mongos server第一次启动或者关掉重启就会从config server加载配置信息,以后如果配置服务器信息变化会通知到所有的mongos server更新自己的状态,这样mongos server就能继续准确路由。
在生产环境中通常需要设置多个config server,因为它存储了分片路由的元数据,防止单点数据丢失。
分片(sharding)是指将数据库拆分,将其分散在不同的机器上的过程。
将数据分散到不同的机器上,不需要功能强大的服务器就可以存储更多的数据和处理更大的负载。
基本思想就是将集合切成小块,这些块分散到若干片里,每个片只负责总数据的一部分,最后通过一个均衡器来对各个分片进行均衡(数据迁移)。
在复制集中,最多只能拥有一个主节点,主节点是唯一能够接收写请求的节点。
MongoDB在主节点进行写操作,并将这些操作记录到主节点的oplog中。
而副节点将会从oplog复制到其本机,并将这些操作应用到自己的数据集上。
副本节点通过应用主节点传来的数据变动操作来保持其数据集与主节点一致。 副本节点也可以通过增加额外参数配置来对应特殊需求。 例如,副本节点可以是non-voting或是priority 0
仲裁节点即投票节点,其本身并不包含数据集,且也无法晋升为主节点。
但是,一旦当前的主节点不可用时,投票节点就会参与到新的主节点选举的投票中。
仲裁节点使用最小的资源并且不要求单独的硬件设备。
投票节点的存在使得复制集可以以偶数个节点存在,而无需为复制集再新增节点。
在生产环境中不要将投票节点运行在复制集的主节点或副本节点机器上。
投票节点与其他复制集节点的交流仅有:选举过程中的投票,心跳检测和配置数据,这些交互都是不加密的。
一、部署:各节点基础配置
apprun用户操作、运行程序
三台主机hosts配置:
sudo vim /etc/hosts 192.168.109.137 mongodb01 192.168.109.138 mongodb02 192.168.109.139 mongodb03
cat >> /etc/security/limits.conf << EOF mongodb soft nproc 65535 mongodb hard nproc 65535 mongodb soft nofile 81920 mongodb hard nofile 81920 EOF
3.关闭防火墙、关闭selinux、配置时间同步、免密认证~等...
4.新增用户apprun、设置sudoers权限
mkdir -pv /apprun/mongo7.0/{logs,yaml,data,pki,bin,pidfile} mkdir -pv /apprun/mongo7.0/data/{config_svr,shard-1,shard-2,shard-3} mkdir -pv /apprun/mongo7.0/logs/{mongos,config_svr,shard-1,shard-2,shard-3}
6.添加yum源,yum安装mongodb7
[mongodb-org-7.0] name=MongoDB Repository baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/7.0/x86_64/ gpgcheck=1 enabled=1 gpgkey=https://www.mongodb.org/static/pgp/server-7.0.asc
sudo yum -y module disable mongodb
sudo yum install -y mongodb-org
关闭开机自启:sudo systemctl disable mongod.service #yum安装防止mongodb用户自启干扰
vim /etc/profile.d/mongodb.sh export MONGODB_HOME=/apprun/mongo7.0 source /etc/profile [apprun@mongodb02 ~]$ mongod --version db version v7.0.9 Build Info: { "version": "7.0.9", "gitVersion": "3ff3a3925c36ed277cf5eafca5495f2e3728dd67", "openSSLVersion": "OpenSSL 1.1.1k FIPS 25 Mar 2021", "modules": [], "allocator": "tcmalloc", "environment": { "distmod": "rhel80", "distarch": "x86_64", "target_arch": "x86_64" } } [apprun@mongodb02 ~]$
sudo cp /usr/bin/mongod /apprun/mongodb/bin/
二、生成mongo-keyfile认证文件
1.在mongodb01节点上执行
openssl rand -base64 756 > ${MONGODB_HOME}/pki/mongo.keyfile
sudo chmod 600 ${MONGODB_HOME}/pki/mongo.keyfile
cd ${MONGODB_HOME}/pki/ rsync -avz --progress -e 'ssh -p 22' ${MONGODB_HOME}/mongo.keyfile mongodb02:${MONGODB_HOME}/pki/ rsync -avz --progress -e 'ssh -p 22' ${MONGODB_HOME}/mongo.keyfile mongodb03:${MONGODB_HOME}/pki/
三、创建Config Server组件集群
cat > ${MONGODB_HOME}/yaml/config_svr.yml << EOF processManagement: fork: true pidFilePath: /apprun/mongo7.0/pidfile/config_svr.pid net: bindIpAll: true port: 27018 ipv6: true maxIncomingConnections: 20000 unixDomainSocket: enabled: true pathPrefix: /apprun/mongo7.0/ storage: dbPath: /apprun/mongo7.0/data/config_svr wiredTiger: engineConfig: cacheSizeGB: 1 systemLog: destination: file path: /apprun/mongo7.0/logs/config_svr/config_svr.log logAppend: true sharding: clusterRole: configsvr replication: oplogSizeMB: 1000 replSetName: configsvr_rs #security: # authorization: enabled # keyFile: /apprun/mongo7.0/pki/mongo.keyfile # clusterAuthMode: keyFile setParameter: connPoolMaxConnsPerHost: 20000 EOF
cd ${MONGODB_HOME}/yaml/ rsync -avz --progress -e 'ssh -p 22' ${MONGODB_HOME}/config_svr.yml mongodb02:${MONGODB_HOME}/yaml/ rsync -avz --progress -e 'ssh -p 22' ${MONGODB_HOME}/config_svr.yml mongodb03:${MONGODB_HOME}/yaml/
3. 创建Config Server启动文件,并将启动文件拷贝到其他Config Server节点
[Unit] Description=MongoDB Config Server After=network.target [Service] Type=forking User=apprun Group=apprun PIDFile=/apprun/mongo7.0/pidfile/config_svr.pid ExecStart=/apprun/mongo7.0/bin/mongod --config /apprun/mongo7.0/yaml/config_svr.yml ExecStop=/apprun/mongo7.0/bin/mongod --shutdown --config /apprun/mongo7.0/yaml/config_svr.yml [Install] WantedBy=multi-user.target
复制到其他Config Server节点
4. 在Config Server各节点启动Config Server服务
sudo systemctl daemon-reload
sudo systemctl start mongodb-config.service
sudo systemctl status mongodb-config.service
sudo systemctl enable mongodb-config.service
sudo netstat -ntlp
5. 在mongodb01上初始化配置Config Server副本集
mongosh --host localhost --port 27018
use admin
config = {_id: "configsvr_rs", members: [ {_id: 0, host: "mongodb01:27018"},
{_id: 1, host: "mongodb02:27018"},
{_id: 2, host: "mongodb03:27018"} ] }
#注:_id: "configsvr_rs"应与config_svr.yml配置文件中的replSetName名称一致,"members" 中的 "host" 为三个节点的IP/主机名和Config Server Port
初始化副本集:
admin> rs.initiate(config)
{ ok: 1 }
查看此时状态:
configsvr_rs [direct: other] admin> rs.status()
四、创建Shard Server组件集群
1. 在mongodb01节点创建Shard Server01、02、03三个副本集的配置文件
cat > ${MONGODB_HOME}/yaml/shard-1.yml << EOF processManagement: fork: true pidFilePath: ${MONGODB_HOME}/pidfile/shard-1.pid net: bindIpAll: true port: 27019 ipv6: true maxIncomingConnections: 20000 unixDomainSocket: enabled: true pathPrefix: ${MONGODB_HOME}/ storage: dbPath: ${MONGODB_HOME}/data/shard-1 wiredTiger: engineConfig: cacheSizeGB: 5 systemLog: destination: file path: ${MONGODB_HOME}/logs/shard-1/shard-1.log logAppend: true sharding: clusterRole: shardsvr replication: oplogSizeMB: 1000 replSetName: shardsvr_rs1 #security: # authorization: enabled # keyFile: ${MONGODB_HOME}/pki/mongo.keyfile # clusterAuthMode: keyFile setParameter: connPoolMaxConnsPerHost: 20000 maxNumActiveUserIndexBuilds: 6 EOF
cat > ${MONGODB_HOME}/yaml/shard-2.yml << EOF processManagement: fork: true pidFilePath: ${MONGODB_HOME}/pidfile/shard-2.pid net: bindIpAll: true port: 27020 ipv6: true maxIncomingConnections: 20000 unixDomainSocket: enabled: true pathPrefix: ${MONGODB_HOME}/ storage: dbPath: ${MONGODB_HOME}/data/shard-2 wiredTiger: engineConfig: cacheSizeGB: 5 systemLog: destination: file path: ${MONGODB_HOME}/logs/shard-2/shard-2.log logAppend: true sharding: clusterRole: shardsvr replication: oplogSizeMB: 1000 replSetName: shardsvr_rs2 #security: # authorization: enabled # keyFile: ${MONGODB_HOME}/pki/mongo.keyfile # clusterAuthMode: keyFile setParameter: connPoolMaxConnsPerHost: 20000 maxNumActiveUserIndexBuilds: 6 EOF
cat > ${MONGODB_HOME}/yaml/shard-3.yml << EOF processManagement: fork: true pidFilePath: ${MONGODB_HOME}/pidfile/shard-3.pid net: bindIpAll: true port: 27021 ipv6: true maxIncomingConnections: 20000 unixDomainSocket: enabled: true pathPrefix: ${MONGODB_HOME}/ storage: dbPath: ${MONGODB_HOME}/data/shard-3 wiredTiger: engineConfig: cacheSizeGB: 5 systemLog: destination: file path: ${MONGODB_HOME}/logs/shard-3/shard-3.log logAppend: true sharding: clusterRole: shardsvr replication: oplogSizeMB: 1000 replSetName: shardsvr_rs3 #security: # authorization: enabled # keyFile: ${MONGODB_HOME}/pki/mongo.keyfile # clusterAuthMode: keyFile setParameter: connPoolMaxConnsPerHost: 20000 maxNumActiveUserIndexBuilds: 6 EOF
2. 将三个副本集配置文件拷贝至其他Shard Server节点
cd ${MONGODB_HOME}/yaml/
rsync -avz --progress -e 'ssh -p 22' ${MONGODB_HOME}/shard-*.yml mongodb02:${MONGODB_HOME}/yaml/
rsync -avz --progress -e 'ssh -p 22' ${MONGODB_HOME}/shard-*.yml mongodb03:${MONGODB_HOME}/yaml/
3. 在mongodb01节点创建Shard Server01、02、03三个副本集的启动文件
sudo vim /usr/lib/systemd/system/mongodb-shard-1.service [Unit] Description=MongoDB Shard Server One After=mongodb-config.service network.target [Service] Type=forking User=apprun Group=apprun PIDFile=/apprun/mongo7.0/pidfile/shard-1.pid ExecStart=/apprun/mongo7.0/bin/mongod --config /apprun/mongo7.0/yaml/shard-1.yml ExecStop=/apprun/mongo7.0/bin/mongod --shutdown --config /apprun/mongo7.0/yaml/shard-1.yml [Install] WantedBy=multi-user.target
sudo vim /usr/lib/systemd/system/mongodb-shard-2.service [Unit] Description=MongoDB Shard Server Two After=mongodb-config.service network.target [Service] Type=forking User=apprun Group=apprun PIDFile=/apprun/mongo7.0/pidfile/shard-2.pid ExecStart=/apprun/mongo7.0/bin/mongod --config /apprun/mongo7.0/yaml/shard-2.yml ExecStop=/apprun/mongo7.0/bin/mongod --shutdown --config /apprun/mongo7.0/yaml/shard-2.yml [Install] WantedBy=multi-user.target
sudo vim /usr/lib/systemd/system/mongodb-shard-3.service [Unit] Description=MongoDB Shard Server Three After=mongodb-config.service network.target [Service] Type=forking User=apprun Group=apprun PIDFile=/apprun/mongo7.0/pidfile/shard-3.pid ExecStart=/apprun/mongo7.0/bin/mongod --config /apprun/mongo7.0/yaml/shard-3.yml ExecStop=/apprun/mongo7.0/bin/mongod --shutdown --config /apprun/mongo7.0/yaml/shard-3.yml [Install] WantedBy=multi-user.target
3.4 将三个Shard Server副本集的启动文件拷贝至其他Shard Server节点[略]
4. 在mongodb各节点启动三个Shard Server服务
sudo systemctl daemon-reload
sudo systemctl start mongodb-shard-1
sudo systemctl start mongodb-shard-2
sudo systemctl start mongodb-shard-3
sudo systemctl status mongodb-shard-1
sudo systemctl status mongodb-shard-2
sudo systemctl status mongodb-shard-3
sudo netstat -ntlp
sudo systemctl enable mongodb-shard-1
sudo systemctl enable mongodb-shard-2
sudo systemctl enable mongodb-shard-3
mongosh --host mongodb01 --port 27019 使用admin数据库,定义副本集配置: use admin 定义config变量,"arbiterOnly":true 代表其为仲裁节点: config = {_id: "shardsvr_rs1", members: [ {_id: 0, host: "mongodb01:27019"}, {_id: 1, host: "mongodb02:27019"}, {_id: 2, host: "mongodb03:27019",arbiterOnly:true}, ] } 注:_id: "shardsvr_rs1"应与shard-1.yml配置文件中的replSetName名称一致, "members" 中的 "host" 为三个节点的IP/主机名和Shard Server 1 Port 初始化副本集: rs.initiate(config); 查看此时状态: admin> rs.status()
mongosh --host mongodb02 --port 27020 使用admin数据库,定义副本集配置: use admin 定义config变量,"arbiterOnly":true 代表其为仲裁节点: config = {_id: "shardsvr_rs2", members: [ {_id: 0, host: "mongodb01:27020",arbiterOnly:true}, {_id: 1, host: "mongodb02:27020"}, {_id: 2, host: "mongodb03:27020"}, ] } 注:_id: "shardsvr_rs2"应与shard-2.yml配置文件中的replSetName名称一致, "members" 中的 "host" 为三个节点的IP/主机名和Shard Server 2 Port 初始化副本集: rs.initiate(config); 查看此时状态: admin> rs.status()
mongosh --host mongodb03 --port 27021 使用admin数据库,定义副本集配置: use admin 定义config变量,"arbiterOnly":true 代表其为仲裁节点: config = {_id: "shardsvr_rs3", members: [ {_id: 0, host: "mongodb01:27021"}, {_id: 1, host: "mongodb02:27021",arbiterOnly:true}, {_id: 2, host: "mongodb03:27021"}, ] } 注:_id: "shardsvr_rs3"应与shard-3.yml配置文件中的replSetName名称一致, "members" 中的 "host" 为三个节点的IP/主机名和Shard Server 3 Port 初始化副本集: rs.initiate(config); 查看此时状态: admin> rs.status()
五、创建Mongos Server路由服务器集群
cat > ${MONGODB_HOME}/yaml/mongos.yml << EOF processManagement: fork: true pidFilePath: ${MONGODB_HOME}/pidfile/mongos.pid net: bindIpAll: true port: 27017 ipv6: true maxIncomingConnections: 20000 unixDomainSocket: enabled: true pathPrefix: ${MONGODB_HOME}/ systemLog: destination: file path: ${MONGODB_HOME}/logs/mongos/mongos.log logAppend: true #security: # keyFile: ${MONGODB_HOME}/pki/mongo.keyfile # clusterAuthMode: keyFile sharding: configDB: configsvr_rs/mongodb01:27018,mongodb02:27018,mongodb03:27018 EOF
sudo vim /usr/lib/systemd/system/mongodb-mongos-server.service [Unit] Description=MongoDB Mongos Server #After=mongodb-config.service mongodb-shard-1.service mongodb-shard-2.service mongodb-shard-3.service network.target After=local-fs.target swap.target [Service] Type=forking User=apprun Group=apprun PIDFile=/apprun/mongo7.0/pidfile/mongos.pid ExecStart=/apprun/mongo7.0/bin/mongos --config /apprun/mongo7.0/yaml/mongos.yml ExecStop=/apprun/mongo7.0/bin/mongos --shutdown --config /apprun/mongo7.0/yaml/mongos.yml [Install] WantedBy=multi-user.target
3. 将mongos的配置文件拷贝至其他Mongos Server节点
cd /apprun/mongo7.0/yaml/
rsync -avz --progress -e 'ssh -p 22' ./mongos.yml mongodb02:/apprun/mongo7.0/yaml/
rsync -avz --progress -e 'ssh -p 22' ./mongos.yml mongodb03:/apprun/mongo7.0/yaml/
4. 将mongos的启动文件拷贝至其他Mongos Server节点(略)
5.在Mongos Server各节点启动Mongos服务
sudo cp /usr/bin/mongos /apprun/mongo7.0/bin/
sudo systemctl daemon-reload
sudo systemctl start mongodb-mongos-server
sudo systemctl status mongodb-mongos-server
sudo netstat -ntlp
sudo systemctl enable mongodb-mongos-server
mongosh --host localhost --port 27017 使用admin数据库,定义副本集配置: use admin 添加各个分片集群 sh.addShard("shardsvr_rs1/mongodb01:27019,mongodb02:27019,mongodb03:27019") sh.addShard("shardsvr_rs2/mongodb01:27020,mongodb02:27020,mongodb03:27020") sh.addShard("shardsvr_rs3/mongodb01:27021,mongodb02:27021,mongodb03:27021") 注:添加各集群分片是如提示 MongoServerError[OperationFailed]: Cannot add shardsvr_rs1/mongo-01:27019,mongo-02:27019,mongo-03:27019 as a shard since the implicit default write concern on this shard is set to {w : 1}, because number of arbiters in the shard's configuration caused the number of writable voting members not to be strictly more than the voting majority. Change the shard configuration or set the cluster-wide write concern using the setDefaultRWConcern command and try again. 这是因为在mongos实例中我们使用命令db.adminCommand({ "getDefaultRWConcern": 1 }) 可以查看到当前mongos默认设置的写入安全机制defaultWriteConcern,默认是 majority (多数确认),这是mongodb5.0后开始的默认设置 , 这意味着当进行写操作时,至少要有超过大多数的数据节点确认写操作成功,才会返回成功的响应, 目前我们是3个节点,mongo系统定义的一半节点数是 (3+1)/2=2,需要超过2,也就是至少要有3个节点写入成功才行, 但是我们设置了一个 仲裁节点,导致3个shard节点中,只有2个可写数据的节点,怎么也不会写成功了,所以导致失败 解决方法,将写入安全级别调低,然后再添加分片 db.adminCommand({ "setDefaultRWConcern" : 1, "defaultWriteConcern" : { "w" : 1 }}) sh.addShard("shardsvr_rs1/mongodb01:27019,mongodb02:27019,mongodb03:27019") sh.addShard("shardsvr_rs2/mongodb01:27020,mongodb02:27020,mongodb03:27020") sh.addShard("shardsvr_rs3/mongodb01:27021,mongodb02:27021,mongodb03:27021") "w" : 1 只要主节点写入成功,就直接返回成功的响应,而不管副节点的同步情况 "w" : majority 超过节点半数【(节点数+1)/2】写入成功,才返回成功响应 "w" : 0 不等待任何节点确认写操作,只需写入到内存就返回成功,这是最低级别的写安全级别,这个配置可以提供写入性能,但也有一定的风险 "w" : 等待指定数量的节点确认写成功
六、开启集群认证功能
1. 在mongos中创建认证用户
创建一个名为admin的超级管理员用户,该用户对所有数据库管理有root权限,可使用db.dropUser("admin")删除该用户
mongosh --host mongodb01 --port 27017 use admin db.createUser({user: "admin", pwd: "Hz@10086", roles: [{ role: "root", db: "admin" }]}) 账号验证操作: admin> db.auth("admin", "Hz@10086") { ok: 1 } 权限说明: Read:允许用户读取指定数据库。 readWrite:允许用户读写指定数据库。 dbAdmin:允许用户在指定数据库中执行管理函数,如索引创建、删除,查看统计或访问system.profile。 userAdmin:允许用户向system.users集合写入,可以找指定数据库里创建、删除和管理用户。 clusterAdmin:只在admin数据库中可用,赋予用户所有分片和复制集相关函数的管理权限。 readAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读权限。 readWriteAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读写权限。 userAdminAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的userAdmin权限。 dbAdminAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的dbAdmin权限。 root:只在admin数据库中可用。超级账号,超级权限。
2. 分别在Shard Server 01、02、03的Primary节点,添加admin用户
mongosh --host mongodb01 --port 27019 use admin db.createUser({user: "admin", pwd: "Hz@10086", roles: [{ role: "root", db: "admin" }]})
mongosh --host mongodb02 --port 27020 use admin db.createUser({user: "admin", pwd: "Hz@10086", roles: [{ role: "root", db: "admin" }]})
mongosh --host mongodb03 --port 27021 use admin db.createUser({user: "admin", pwd: "Hz@10086", roles: [{ role: "root", db: "admin" }]})
七、开启各组件安全认证机制
cat > /apprun/clear_annotate.sh << EOF #!/bin/bash path="/apprun/mongo7.0/yaml/" files=("config_svr.yml" "shard-1.yml" "shard-2.yml" "shard-3.yml" "mongos.yml") # 遍历文件列表 for file in "${files[@]}" do # 检查文件是否存在 if [ -f "${path}${file}" ]; then # 移除指定行前的#号 sed -i '/security:/{s/^#//}' "${path}${file}" sed -i '/authorization:/{s/^#//}' "${path}${file}" sed -i '/keyFile:/{s/^#//}' "${path}${file}" sed -i '/clusterAuthMode:/{s/^#//}' "${path}${file}" else echo "文件 ${path}${file} 不存在." fi done echo "处理完成." EOF
sudo systemctl stop mongodb-mongos-server sudo systemctl stop mongodb-shard-3 sudo systemctl stop mongodb-shard-2 sudo systemctl stop mongodb-shard-1 sudo systemctl stop mongodb-config.service sudo netstat -ntlp
集群重启顺序: 1 config 集群 > 2 shard 集群 > 3 mongos 集群 shard 集群最好分开起,避免shard server 1、2、3的主都在第一台上;shard server 1在第一台先起,那么shard server 2就在第二台先起... sudo systemctl restart mongodb-config.service sudo systemctl status mongodb-config.service sudo systemctl restart mongodb-shard-1 sudo systemctl status mongodb-shard-1 sudo systemctl restart mongodb-shard-2 sudo systemctl status mongodb-shard-2 sudo systemctl restart mongodb-shard-3 sudo systemctl status mongodb-shard-3 sudo systemctl restart mongodb-mongos-server sudo systemctl status mongodb-mongos-server sudo netstat -ntlp
注:在启动Shard Server组件时,至少需要两个Config Server节点起来,也就是Config Server集群可用才行
4.使用admin用户登录mongos,创建普通用户
创建一个名为testuser的普通用户,该用户对testdb数据库有读写权限,可使用db.dropUser("testuser")删除该用户
mongosh -u admin -p Hz@10086 mongodb01:27017/admin
use testdb
db.createUser({user:"testuser", pwd:"Hzyh@10085", roles:[{role:"readWrite",db:"testdb"}]});
账号验证操作:
testdb> db.auth("testuser", "Hzyh@10085")
{ ok: 1 }
5. 客户端连接mongodb集群
mongosh mongodb://'testuser':'Hzyh@10085'@192.168.109.137:27017,192.168.109.138:27017,192.168.109.139:27017/testdb?authSource=testdb