Mongodb分片集群
介绍
副本集帮助我们解决读请求扩展、高可用等问题。随着业务场景进一 步增长,可能会出现以下问题:
存储容量超出单机磁盘容量
活跃数据集超出单机内存容量:很多读请求需要从磁盘读取
写入量超出单机 IOPS 上限
解决此问题,有两个途径: 1.扩展服务器硬件性能,比如增加磁盘和内存。 2.增加服务器数量。 从成本和便捷性上考虑,肯定是第2个更加合适。 而Mongodb分片技术就是基于第2个途径来解决以上问题的。
MongoDB 分片集群(Sharded Cluster)是对数据进行水平扩展的一种方式,分片集群用来支持大数据集和高吞吐量的业务场景。 本质上,Mongodb的分片技术就是将数据按预定的算法均匀地分布到不同的节点上,类似于磁盘的raid5。只不过它的每个节点都是一组一组的副本集。
架构
分片集群由3个组件组成:
1.路由mongos
数据库集群请求的入口,所有的请求都通过mongos进行协调,不需要在应用程序添加一个路由选择器,mongos自己就是一个请求分发中心,它负责把对应的数据请求请求转发到对应的shard服务器上。在生产环境通常有多mongos作为请求的入口,防止其中一个挂掉所有的mongodb请求都没有办法操作。
2.配置服务器configserver
存储所有数据库元信息(路由、分片)的配置。 mongos本身没有物理存储分片服务器和数据路由信息,只是缓存在内存里,配置服务器则实际存储这些数据。 mongos第一次启动或者关掉重启就会从config server加载配置信息,以后如果配置服务器信息变化会通知到所有的mongos更新自己的状态,这样mongos就能继续准确路由。 在生产环境通常有多个 config server 配置服务器,因为它存储了分片路由的元数据,防止数据丢失!
3.分片shard
存储用户数据,不同shard保存不同用户数据
存储了一个集合部分数据的MongoDB实例,每个分片是单独的mongodb服务或者副本集,在生产环境中,所有的分片都应该是副本集
搭建

1.机器规划 | 节点名称 | 主机名 | IP地址 | 角色 | | :—- | :—- | :—- | :—- | | 节点1 | centos8 | 192.168.195.105 | mongos、config server、shard1主节点、shard2从节点、shard3从节点 | | 节点2 | centos8-1 | 192.168.195.106 | mongos、 config server、shard1从节点、shard2从节点、shard3主节点 | | 节点3 | centos8-2 | 192.168.195.107 | mongos、 config server、shard1从节点、shard2主节点、shard3从节点 |
2.端口划分 | 角色 | 端口 | | :—- | :—- | | mongos | 20000 | | config server | 21000 | | shard1 | 27001 | | shard2 | 27002 | | shard3 | 27003 |
3.准备工作 三个节点分别执行
# 修改各自的主机名
sudo hostnamectl set-hostname centos8
sudo hostnamectl set-hostname centos8-1
sudo hostnamectl set-hostname centos8-2
# 修改hosts文件,每台加入以下全部内容
cat >> /etc/hosts <<EOF
192.168.195.105 centos8
192.168.195.106 centos8-1
192.168.195.107 centos8-2
EOF
# 关闭防火墙和selinux
sudo systemctl stop firewalld
sudo systemctl disable firewalld
sudo sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
sudo setenforce 0
4.删除之前做实验的历史数据(三个节点都操作)
systemctl stop mongodb
rm -rf /data/mongodb/*
5.节点上创建目录(三个节点上都操作)
mkdir -p /data/mongodb/{mongos,config,shard1,shard2,shard3}
chown -R mongodb /data/mongodb/
config server配置
6.config server配置 在节点1上编辑配置文件
vi /usr/local/mongodb/conf/config.conf ## 内容如下
systemLog:
#MongoDB发送所有日志输出的目标指定为文件
destination: file
#mongod或mongos应向其发送所有诊断日志记录信息的日志文件的路径
path: "/usr/local/mongodb/logs/configsvr.log"
#当mongos或mongod实例重新启动时,mongos或mongod会将新条目附加到现有日志文件的末尾
logAppend: true
storage:
#mongod实例存储其数据的目录。storage.dbPath设置仅适用于mongod
dbPath: "/data/mongodb/config"
journal:
#启用或禁用持久性日志以确保数据文件保持有效和可恢复。
enabled: true
processManagement:
#启用在后台运行mongos或mongod进程的守护进程模式。
fork: true
#指定用于保存mongos或mongod进程的进程ID的文件位置,其中mongos或mongod将写入其PID
pidFilePath: "/usr/local/mongodb/logs/configsvr.pid"
#从中加载时区数据库的完整路径
timeZoneInfo: /usr/share/zoneinfo
net:
#服务实例绑定所有IP,有副作用,副本集初始化的时候,节点名字会自动设置为本地域名,而不是ip
#bindIpAll: true
#服务实例绑定的IP,0.0.0.0让所有机器都能连接。
bindIp: 0.0.0.0
#bindIp
#绑定的端口
port: 21000
# 安全配置
#security:
# 配置密码文件
#keyFile: /usr/local/mongodb/conf/keyfile
replication:
#副本集的名称
replSetName: "config"
sharding:
clusterRole: configsvr
然后将节点1上的配置文件拷贝到节点2和节点3
scp /usr/local/mongodb/conf/config.conf centos8-1:/usr/local/mongodb/conf/config.conf
scp /usr/local/mongodb/conf/config.conf centos8-2:/usr/local/mongodb/conf/config.conf
编辑systemd服务脚本(三节点一样)
vi /lib/systemd/system/configsvr.service ##内容如下
[Unit]
Description=mongodb
After=network.target remote-fs.target nss-lookup.target
[Service]
User=mongodb
Type=forking
ExecStart=/usr/local/mongodb/bin/mongod --config /usr/local/mongodb/conf/config.conf
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target
三个节点上,启动服务
systemctl daemon-reload
systemctl start configsvr.service
登录节点1
mongosh centos:21000 ##登录后执行如下命令,复制粘贴即可
rs.initiate(
{
_id: "config",
version: 1,
members: [
{ _id: 0, host : "centos8:21000" },
{ _id: 1, host : "centos8-1:21000"},
{ _id: 2, host : "centos8-2:21000" }
]
}
)
配置路由
在节点1上编辑配置文件
vi /usr/local/mongodb/conf/mongos.conf ## 内容如下
systemLog:
#MongoDB发送所有日志输出的目标指定为文件
destination: file
#mongod或mongos应向其发送所有诊断日志记录信息的日志文件的路径
path: "/usr/local/mongodb/logs/mongos.log"
#当mongos或mongod实例重新启动时,mongos或mongod会将新条目附加到现有日志文件的末尾
logAppend: true
processManagement:
#启用在后台运行mongos或mongod进程的守护进程模式。
fork: true
#指定用于保存mongos或mongod进程的进程ID的文件位置,其中mongos或mongod将写入其PID
pidFilePath: "/usr/local/mongodb/logs/mongos.pid"
#从中加载时区数据库的完整路径
timeZoneInfo: /usr/share/zoneinfo
net:
#服务实例绑定所有IP,有副作用,副本集初始化的时候,节点名字会自动设置为本地域名,而不是ip
#bindIpAll: true
#服务实例绑定的IP,0.0.0.0让所有机器都能连接。
bindIp: 0.0.0.0
#bindIp
#绑定的端口
port: 20000
# 安全配置
#security:
# 配置密码文件
#keyFile: /usr/local/mongodb/conf/keyfile
sharding:
configDB: config/centos8:21000,centos8-1:21000,centos8-2:21000
然后将节点1上的配置文件拷贝到节点2和节点3
scp /usr/local/mongodb/conf/mongos.conf centos8-1:/usr/local/mongodb/conf/mongos.conf
scp /usr/local/mongodb/conf/mongos.conf centos8-2:/usr/local/mongodb/conf/mongos.conf
编辑systemd服务脚本(三节点一样)
vi /lib/systemd/system/mongos.service ##内容如下
[Unit]
Description=mongos
After=network.target remote-fs.target nss-lookup.target
[Service]
User=mongodb
Type=forking
ExecStart=/usr/local/mongodb/bin/mongos --config /usr/local/mongodb/conf/mongos.conf
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target
三个节点上,启动服务
systemctl daemon-reload
systemctl start mongos.service
启用分片
mongosh centos:20000
sh.addShard("shard1/centos8:27001,centos8-1:27001,centos8-2:27001")
sh.addShard("shard2/centos8:27002,centos8-1:27002,centos8-2:27002")
sh.addShard("shard3/centos8:27003,centos8-1:27003,centos8-2:27003")
查看状态
sh.status()
开启认证
创建root用户
use admin
db.createUser({user:"root",pwd:"aminglinux.com",roles:["root"]})
创建keyfile,在节点1上操作
openssl rand -base64 20 > /usr/local/mongodb/conf/keyfile
chmod 400 /usr/local/mongodb/conf/keyfile
chown mongodb /usr/local/mongodb/conf/keyfile
将keyfile拷贝到另外两台机器
scp /usr/local/mongodb/conf/keyfile centos8-1:/usr/local/mongodb/conf/keyfile
scp /usr/local/mongodb/conf/keyfile centos8-2:/usr/local/mongodb/conf/keyfile
节点2和节点3上,更改keyfile权限
chmod 400 /usr/local/mongodb/conf/keyfile
chown mongodb /usr/local/mongodb/conf/keyfile
编辑配置文件(全部三个节点,操作一样)
cd /usr/local/mongodb/conf
##将所有配置security那部分配置前面的#删除掉
sed -i -e 's/#security/security/' -e 's/#keyFile/keyFile/' *.conf
重启所有服务(全部三个节点,操作一样)
for s in configsvr shard1 shard2 shard3 mongos ; do systemctl restart $s; done
测试
use admin
db.auth("root","aminglinux.com")
use testdb
sh.enableSharding("testdb") ##指定要分片的数据库
sh.shardCollection("testdb.table1", {id: "hashed"} ) ##指定数据库里需要分片的集合和片键
for (var i = 1; i <= 10000; i++) db.table1.insert({id:i*123,uid:i}) ##插入测试数据
db.table1.stats() ##查看table1状态