MongoDB分片集
分片集基本概念
以往的副本集会受到硬件配置的限制,如果写性能出现瓶颈,只能依靠拉高CPU、内存配置来提升性能,而分片集群无需考虑这点,毕竟整个集群都是由不同节点组合对外服务,如果性能出现瓶颈,只需要继续增加分片节点即可,相较于副本集群,分片集群的上限更高。
Router路由:负责接收、分发客户端的读写请求,类似于代理中间件;Shard分片:存储数据、处理读写请求的具体节点;Config配置:存储路由、分片节点的元数据和配置信息;
这三种角色简单理解就是:一个负责请求调度、一个负责数据存储、一个负责配置管理,不过这里要注意,路由可以由一或多个mongos节点组成,config同理,而shard则并非单独的mongodb节点,而是一个个的replicaSet复制集(副本集群)。
MongoDB分片集群中的概念
Shard Rules:分片规则,也叫分片算法,指分发读写请求的逻辑,如随机、取模等;Shard Key:分片键,也叫路由键,指基于文档中的哪个字段进行分片计算;Document:文档,这个概念在前面就一直接触过,等价于MySQL中的一条数据;Chunk:块,指包含一定范围内多个文档的数据段,属于集群中分割、存储数据的基本单位;Shard:分片,每个分片都由一个副本集群组成,一个分片中可以存储多个Chunk数据块;Cluster:集群,由多个Shard分片组成,统一对外提供读写服务。
Redis和MongoDB的区别
MongoDB分片集群对比Redis分片集群,或者传统的分库分表技术而言,还有一个无与伦比的优势,即:在集群的分片动态伸缩(数量发生变化)时,会自动触发数据迁移机制,由MongoDB内部来自动维护数据的平衡,无需任何外力介入!像“数据均衡”这个功能,无论在Redis、还是分库分表中,都需要开发者手动完成数据迁移,维护成本特别高。
分片集群搭建
基于“硬性底线”,配置需求:
至少 9 台独立服务器(或虚拟机):3台用于配置服务器副本集(Config Server),3台用于第一个分片的副本集(Shard1),另外3台用于第二个分片的副本集(Shard2);外加 2台独立部署
mongos路由进程(可与上述9台中的任意节点复用物理机,但严禁与任何mongod进程共用同一服务器,故实际仍需额外2台,或使用容器/PaaS单独调度)。
若按严格物理隔离(最佳实践),则需要 11台独立机器:
3台(Config Server,每台最低 2核4GB,存储建议SSD 50GB+)
3台(Shard1 副本集,生产推荐 8核32GB+,存储按数据量)
3台(Shard2 副本集,同规格)
2台(
mongos,最低 4核8GB,无状态,可共置于应用侧)
如何搭建完整的副本集群,前面已经学习过了,这样最终所需的节点数量变为了:2+2+1=5个,把所有涉及到副本集群的角色,全都阉割成一个节点,也就是每个副本集只有主节点,不为其添加副本节点、仲裁节点
机器规划
设置环境变量永久生效(为了防止操作下面步骤指令无效请设置好环境变量)
# 编辑文件
vim /etc/profile
# 在末尾添加
export PATH=$PATH:/usr/local/mongodb/bin
# 重新加载系统环境变量配置文件,立即生效
source /etc/profileMongoDB 内部副本集通信使用的是主机名
# 在所有机器上执行
cat >> /etc/hosts << 'EOF'
192.168.7.110 MongoDB-1
192.168.7.111 MongoDB-2
192.168.7.112 MongoDB-3
192.168.7.113 MongoDB-4
192.168.7.114 MongoDB-5
EOF所有机器前置准备(5台都执行)
# 1. 创建目录
mkdir -p /usr/local/mongodb/{data,log,conf}/standalone
# 2. 目录结构
# /usr/local/mongodb/
# ├── data/standalone/ 数据目录
# ├── log/standalone/ 日志目录
# └── conf/standalone/ 配置文件目录
# 安装MongoDB及mongosh逐台机器部署
机器1(192.168.7.110)——部署分片1
# 编辑配置文件
vim /usr/local/mongodb/conf/standalone/mongod.conf
# 添加以下内容
systemLog: # 系统日志配置
destination: file # 日志输出目标:文件
path: "/usr/local/mongodb/log/standalone/mongo.log" # 日志文件存放路径
logAppend: true # 重启时追加写入日志,不覆盖原有日志
storage: # 存储配置
dbPath: "/usr/local/mongodb/data/standalone" # 数据文件存放路径
processManagement: # 进程管理配置
fork: true # 以后台守护进程方式运行(后台运行)
pidFilePath: "/usr/local/mongodb/conf/standalone/mongod.pid" # PID进程ID文件存放路径
net: # 网络配置
bindIp: 0.0.0.0 # 监听所有IP地址(允许任何机器连接)
port: 27017 # 服务端口号
replication: # 副本集配置
replSetName: zhuzi-shard-1 # 副本集名称
sharding: # 分片集群配置
clusterRole: shardsvr # 节点角色:分片节点(shardsvr)
# 启动
mongod -f /usr/local/mongodb/conf/standalone/mongod.conf
# 初始化副本集
mongosh 192.168.7.110:27017 --eval "rs.initiate()"
'生产环境存在副本节点(需要在主节点上添加)(当前环境下无需操作)'
mongosh 192.168.7.110:27017 --eval "rs.add('192.168.7.xxx:27017')"
mongosh 192.168.7.110:27017 --eval "rs.add('192.168.7.xxx:27017')"
# 验证
mongosh 192.168.7.110:27017 --eval "rs.status()"机器2(192.168.7.111)——部署分片2
# 编辑配置文件
vim /usr/local/mongodb/conf/standalone/mongod.conf
# 添加以下内容
systemLog: # 系统日志配置
destination: file # 日志输出目标:文件
path: "/usr/local/mongodb/log/standalone/mongo.log" # 日志文件存放路径
logAppend: true # 重启时追加写入日志,不覆盖原有日志
storage: # 存储配置
dbPath: "/usr/local/mongodb/data/standalone" # 数据文件存放路径
processManagement: # 进程管理配置
fork: true # 以后台守护进程方式运行(后台运行)
pidFilePath: "/usr/local/mongodb/conf/standalone/mongod.pid" # PID进程ID文件存放路径
net: # 网络配置
bindIp: 0.0.0.0 # 监听所有IP地址(允许任何机器连接)
port: 27017 # 服务端口号
replication: # 副本集配置
replSetName: zhuzi-shard-2 # 副本集名称
sharding: # 分片集群配置
clusterRole: shardsvr # 节点角色:分片节点(shardsvr)
# 启动
mongod -f /usr/local/mongodb/conf/standalone/mongod.conf
# 初始化副本集
mongosh 192.168.7.111:27017 --eval "rs.initiate()"
'生产环境存在副本节点(需要在主节点上添加)(当前环境下无需操作)'
mongosh 192.168.7.111:27017 --eval "rs.add('192.168.7.xxx:27017')"
mongosh 192.168.7.111:27017 --eval "rs.add('192.168.7.xxx:27017')"
# 验证
mongosh 192.168.7.111:27017 --eval "rs.status()"机器3(192.168.7.112)——部署配置节点
# 编辑配置文件
vim /usr/local/mongodb/conf/standalone/mongod.conf
# 添加以下内容
systemLog: # 系统日志配置
destination: file # 日志输出目标:文件
path: "/usr/local/mongodb/log/standalone/mongo.log" # 日志文件存放路径
logAppend: true # 重启时追加写入日志,不覆盖原有日志
storage: # 存储配置
dbPath: "/usr/local/mongodb/data/standalone" # 数据文件存放路径
processManagement: # 进程管理配置
fork: true # 以后台守护进程方式运行(后台运行)
pidFilePath: "/usr/local/mongodb/conf/standalone/mongod.pid" # PID进程ID文件存放路径
net: # 网络配置
bindIp: 0.0.0.0 # 监听所有IP地址(允许任何机器连接)
port: 27017 # 服务端口号
replication: # 副本集配置
replSetName: zhuzi-config # 副本集名称
sharding: # 分片集群配置
clusterRole: configsvr # 节点角色:配置节点(configsvr)
# 启动
mongod -f /usr/local/mongodb/conf/standalone/mongod.conf
# 初始化副本集
mongosh 192.168.7.112:27017 --eval "rs.initiate()"
'生产环境存在副本节点(需要在主节点上添加)(当前环境下无需操作)'
mongosh 192.168.7.112:27017 --eval "rs.add('192.168.7.xxx:27017')"
mongosh 192.168.7.112:27017 --eval "rs.add('192.168.7.xxx:27017')"
# 验证
mongosh 192.168.7.112:27017 --eval "rs.status()"机器4(192.168.7.113)——部署路由1
# 编辑配置文件
vim /usr/local/mongodb/conf/standalone/mongos.conf
# 添加以下内容
systemLog: # 系统日志配置
destination: file # 日志输出目标:文件
path: "/usr/local/mongodb/log/standalone/mongo.log" # 日志文件存放路径
logAppend: true # 重启时追加写入日志,不覆盖原有日志
processManagement: # 进程管理配置
fork: true # 以后台守护进程方式运行(后台运行)
pidFilePath: "/usr/local/mongodb/conf/standalone/mongos.pid" # PID进程ID文件存放路径
net: # 网络配置
bindIp: 0.0.0.0 # 监听所有IP地址(允许任何机器连接)
port: 27017 # 服务端口号
sharding: # 分片集群配置
configDB: zhuzi-config/192.168.7.112:27017 # 指定配置节点地址
'生产环境存在副本节点(需要一起添加)(当前环境下无需操作)'
configDB: zhuzi-config/192.168.7.xxx:27017,192.168.7.xxx:27017,192.168.7.xxx:27017
# 启动(注意:路由节点使用 mongos 命令,不是 mongod)
mongos -f /usr/local/mongodb/conf/standalone/mongos.conf
# 验证连接
mongosh 192.168.7.113:27017 --eval "db.isMaster()"机器5(192.168.7.114)——部署路由2
# 编辑配置文件
vim /usr/local/mongodb/conf/standalone/mongos.conf
# 添加以下内容
systemLog: # 系统日志配置
destination: file # 日志输出目标:文件
path: "/usr/local/mongodb/log/standalone/mongo.log" # 日志文件存放路径
logAppend: true # 重启时追加写入日志,不覆盖原有日志
processManagement: # 进程管理配置
fork: true # 以后台守护进程方式运行(后台运行)
pidFilePath: "/usr/local/mongodb/conf/standalone/mongos.pid" # PID进程ID文件存放路径
net: # 网络配置
bindIp: 0.0.0.0 # 监听所有IP地址(允许任何机器连接)
port: 27017 # 服务端口号
sharding: # 分片集群配置
configDB: zhuzi-config/192.168.7.112:27017 # 指定配置节点地址
'生产环境存在副本节点(需要一起添加)(当前环境下无需操作)'
configDB: zhuzi-config/192.168.7.xxx:27017,192.168.7.xxx:27017,192.168.7.xxx:27017
# 启动(注意:路由节点使用 mongos 命令,不是 mongod)
mongos -f /usr/local/mongodb/conf/standalone/mongos.conf
# 验证连接
mongosh 192.168.7.114:27017 --eval "db.isMaster()"添加分片到集群(在任意路由节点执行)
# 连接路由1或路由2:
mongosh 192.168.7.113:27017
# 或
mongosh 192.168.7.114:27017
# 执行添加分片命令:
use admin;
// 用主机名添加分片1
sh.addShard("zhuzi-shard-1/MongoDB-1:27017");
'生产环境存在副本节点(需要一起添加)(当前环境下无需操作)'
sh.addShard("zhuzi-shard-1/MongoDB-x:27017,MongoDB-x:27017,MongoDB-x:27017");
// 用主机名添加分片2
sh.addShard("zhuzi-shard-2/MongoDB-2:27017");
'生产环境存在副本节点(需要一起添加)(当前环境下无需操作)'
sh.addShard("zhuzi-shard-1/MongoDB-x:27017,MongoDB-x:27017,MongoDB-x:27017");
// 查看分片状态
sh.status();验证测试
# 连接路由1(MongoDB-4)
mongosh 192.168.7.113:27017
# 或者连接路由2(MongoDB-5)
mongosh 192.168.7.114:27017
// 切换到测试库
use zhuzi;
// 对数据库启用分片
sh.enableSharding("zhuzi");
// 对集合指定分片键(使用 hashed 分片,数据分布更均匀)
sh.shardCollection("zhuzi.pandas", { _id: "hashed" });
// 插入测试数据
db.pandas.insertOne({_id: 1, name: "肥肥"});
db.pandas.insertOne({_id: 2, name: "萌萌"});
db.pandas.insertOne({_id: 3, name: "豆豆"});
db.pandas.insertOne({_id: 4, name: "花花"});
db.pandas.insertOne({_id: 5, name: "球球"});
// 查看数据分布
db.pandas.getShardDistribution();
// 查看分片集群整体状态
sh.status();最终架构图
┌─────────────────┐
│ 路由节点 │
│ MongoDB-4:27017 │
│ MongoDB-5:27017 │
└────────┬────────┘
│
┌────────▼────────┐
│ 配置节点 │
│ MongoDB-3:27017 │
│ zhuzi-config │
└─────────────────┘
│
┌────────────────────┼────────────────────┐
│ │
┌───────▼───────┐ ┌───────▼───────┐
│ 分片1 │ │ 分片2 │
│ MongoDB-1 │ │ MongoDB-2 │
│ zhuzi-shard-1 │ │ zhuzi-shard-2 │
│ 业务数据 50% │ │ 业务数据 50% │
└───────────────┘ └───────────────┘集群信息卡片
╔══════════════════════════════════════════════════════════════╗
║ 🎊 分片集群搭建成功 🎊 ║
╠══════════════════════════════════════════════════════════════╣
║ 分片1: MongoDB-1:27017 (zhuzi-shard-1) ✅ ║
║ 分片2: MongoDB-2:27017 (zhuzi-shard-2) ✅ ║
║ 配置: MongoDB-3:27017 (zhuzi-config) ✅ ║
║ 路由1: MongoDB-4:27017 ✅ ║
║ 路由2: MongoDB-5:27017 ✅ ║
╠══════════════════════════════════════════════════════════════╣
║ 已分片数据库: zhuzi ║
║ 已分片集合: zhuzi.pandas ║
║ 分片键: { _id: "hashed" } ║
║ 数据块数: 4 个 ║
║ 当前数据: 5 条文档 ║
╚══════════════════════════════════════════════════════════════╝故障排查清单
MongoDB分片集
本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
评论交流
欢迎留下你的想法