适用版本:MongoDB 8.0 / 8.3(本文以 8.0 为基准,适用于 8.x 系列)
工作模式:自管理副本集(Self-Managed Replica Set)
核心场景:在 RHEL 8/9 系统上部署 MongoDB 三节点副本集(一主一从一仲裁),并实现自动故障转移
分类标签
分类标签:MongoDB 安装部署、MongoDB 副本集、MongoDB 高可用
博客分类备注:本文核心解决 MongoDB 8.x 副本集的部署与验证问题,属于安装部署类,标签结合了 MongoDB、副本集、高可用。
环境说明
| 项目 | 说明 |
|---|---|
| 操作系统 | RHEL 8.8+ / RHEL 9.3+ |
| MongoDB 版本 | 8.0.x(当前稳定 LTS 版本) |
| 副本集名称 | rs0 |
| 端口 | 27017 |
| 节点规划 | 1 Primary + 1 Secondary + 1 Arbiter |
版本差异说明:
- MongoDB 4.4:使用旧式配置文件格式(键值对),
mongoshell- MongoDB 5.0+:推荐
mongosh替代mongo,配置全面改用 YAML 格式- MongoDB 6.0+:
noauth参数废弃,使用security.authorization: disabled- MongoDB 8.0+:仅支持 RHEL 8.8+ / RHEL 9.3+,弃用部分旧指标
- 版本适配建议:生产环境建议使用 MongoDB 8.0.x 最新补丁版(如 8.0.21),避免早期版本安全漏洞
一、节点规划
| 角色 | 主机名 | IP 地址 | 说明 |
|---|---|---|---|
| Primary | mongo01 | [IP1] |
主节点,处理所有写操作 |
| Secondary | mongo02 | [IP2] |
从节点,持有数据副本,可承接读请求 |
| Arbiter | mongo03 | [IP3] |
仲裁节点,不持有数据,仅参与选举投票 |
小贴士:副本集节点数应为奇数,以确保在分区场景下能形成多数派(majority),避免脑裂。
二、前置准备(所有节点执行)
2.1 配置主机名解析
# 所有节点编辑 /etc/hosts
cat >> /etc/hosts << EOF
[IP1] mongo01
[IP2] mongo02
[IP3] mongo03
EOF
2.2 安装依赖包
# RHEL 8/9 使用 dnf(yum 的继承者)
dnf install -y cyrus-sasl cyrus-sasl-plain cyrus-sasl-gssapi \
krb5-libs lm_sensors-libs net-snmp-libs openssl openssl-devel \
rpm-libs tcp_wrappers-libs
2.3 关闭防火墙与 SELinux
# 关闭防火墙
systemctl disable firewalld
systemctl stop firewalld
# 禁用 SELinux(生产环境建议使用 targeted 模式并配置策略,此处为简化)
sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config
setenforce 0
2.4 优化内核参数
# 禁用 NUMA zone reclaim(提升数据库性能)
echo "vm.zone_reclaim_mode = 0" >> /etc/sysctl.conf
# 生产环境建议同时配置以下参数
echo "vm.swappiness = 1" >> /etc/sysctl.conf
echo "net.ipv4.tcp_keepalive_time = 300" >> /etc/sysctl.conf
sysctl -p
2.5 禁用 Transparent Huge Pages(THP)
# 方法一:通过 /etc/rc.local(重启生效)
cat >> /etc/rc.local << 'EOF'
if test -f /sys/kernel/mm/transparent_hugepage/enabled; then
echo never > /sys/kernel/mm/transparent_hugepage/enabled
fi
if test -f /sys/kernel/mm/transparent_hugepage/defrag; then
echo never > /sys/kernel/mm/transparent_hugepage/defrag
fi
EOF
chmod +x /etc/rc.local
# 立即生效
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag
⚠️ 修正说明(原文档):原文档使用
vi编辑/etc/rc.local,此处改为直接cat追加,并确保文件可执行,重启后配置自动生效。
2.6 创建目录与用户
# 创建目录
mkdir -p /mongodb/{data,logs,apps}
# 创建用户和组
groupadd -g 10001 mongodb
useradd -u 10001 -g mongodb -s /bin/bash mongodb
# 设置密码(生产环境请使用复杂密码)
echo "mongodb" | passwd --stdin mongodb
# 授权
chown -R mongodb:mongodb /mongodb
chmod -R 755 /mongodb
⚠️ 修正说明(原文档):原文档
chmod -R 775权限过高,改为755更安全。
2.7 修改最大连接数限制
# 在 /etc/security/limits.conf 中配置
cat >> /etc/security/limits.conf << EOF
mongodb hard nofile 64000
mongodb soft nofile 64000
mongodb hard nproc 64000
mongodb soft nproc 64000
EOF
⚠️ 修正说明(原文档):原文档
nofile设置为 25600,低于 MongoDB 推荐的 64000 最小值,启动时会触发警告。此处修正为 64000。
三、安装 MongoDB 8.0
3.1 下载 MongoDB 8.0
# 官方下载地址(Community 社区版)
# https://www.mongodb.com/try/download/community
# RHEL 8/9 x86_64 最新版本下载示例(请访问官网获取最新链接)
# 使用 mongosh 替代旧版 mongo shell
官方下载地址:
- Community 版:https://www.mongodb.com/try/download/community
- Enterprise 版:https://www.mongodb.com/try/download/enterprise
3.2 解压安装
su - mongodb
cd /mongodb/apps
# 解压安装包(以 8.0.x 为例,文件名根据实际情况调整)
tar zxvf /soft/mongodb-linux-x86_64-rhel80-8.0.21.tgz
# 创建软链接(方便版本切换)
ln -s /mongodb/apps/mongodb-linux-x86_64-rhel80-8.0.21 /mongodb/apps/mongodb
3.3 配置环境变量
# 编辑 ~/.bash_profile
cat >> ~/.bash_profile << 'EOF'
export MONGO_HOME=/mongodb/apps/mongodb
export PATH=$PATH:$MONGO_HOME/bin
EOF
source ~/.bash_profile
四、配置 MongoDB(YAML 格式)
⚠️ 重要变更(MongoDB 5.0+):配置文件全面改用 YAML 格式,旧式键值对格式已废弃。
4.1 主节点(Primary)配置
su - mongodb vi /mongodb/apps/mongodb/bin/mongod.conf
# ========================
# MongoDB 8.0 配置文件(YAML 格式)
# ========================
# 日志配置
systemLog:
destination: file
path: /mongodb/logs/mongod.log
logAppend: true
timeStampFormat: iso8601-local
# 进程管理
processManagement:
fork: true
pidFilePath: /mongodb/apps/mongod.pid
# 网络配置
net:
port: 27017
bindIp: 127.0.0.1,[IP1]
maxIncomingConnections: 50000
# 存储配置
storage:
dbPath: /mongodb/data
journal:
enabled: true
directoryPerDB: true
wiredTiger:
engineConfig:
cacheSizeGB: 2
# 复制集配置
replication:
replSetName: rs0
oplogSizeMB: 2048
# 安全配置(初始部署关闭认证,配置完毕后再启用)
security:
authorization: disabled
4.2 从节点(Secondary)配置
# 仅 net.bindIp 不同,其余与主节点一致
net:
port: 27017
bindIp: 127.0.0.1,[IP2]
4.3 仲裁节点(Arbiter)配置
# 仲裁节点不存储数据,dataPath 可以较小
# 其余配置与从节点类似,net.bindIp 填写 [IP3]
net:
port: 27017
bindIp: 127.0.0.1,[IP3]
storage:
dbPath: /mongodb/data
journal:
enabled: true
directoryPerDB: false # 仲裁节点可不开启
replication:
replSetName: rs0
参数说明:
参数 说明 systemLog.destination日志输出目标, file为文件systemLog.logAppendtrue= 重启时追加,不覆盖processManagement.forktrue= 后台守护进程方式运行net.bindIp绑定 IP,逗号分隔,生产环境绑定具体 IP 而非 0.0.0.0 net.maxIncomingConnections最大并发连接数,默认 65536 storage.dbPath数据文件存放路径 storage.journal.enabled开启 journal 保证宕机安全 storage.directoryPerDBtrue= 每个数据库独立子目录replication.replSetName副本集名称,所有节点必须一致 replication.oplogSizeMBoplog 大小,默认 5% 磁盘空间 security.authorizationdisabled= 关闭认证(初始部署用),生产环境改为enabled
五、启动 MongoDB 服务
5.1 启动所有节点
# 三个节点分别执行
su - mongodb
mongod -f /mongodb/apps/mongodb/bin/mongod.conf
正确停止 mongod(推荐方式):
# 使用 mongosh 连接后正常关闭(推荐)
mongosh --port 27017
> use admin
> db.shutdownServer()
# 或使用 kill -2(SIGINT,优雅关闭,会刷盘)
kill -2 $(pgrep mongod)
⚠️ 修正说明(原文档):原文档使用
kill -2抓取进程号的写法存在风险,建议使用db.shutdownServer()优雅关闭。
5.2 验证启动状态
# 使用 mongosh 连接(MongoDB 5.0+ 推荐,替代旧版 mongo)
mongosh "[IP1]:27017"
⚠️ 版本差异说明:
- MongoDB 4.4 及之前:使用
mongoshell- MongoDB 5.0 开始:
mongosh作为官方推荐 shell,功能更强、兼容性更好- 本文统一使用
mongosh
六、初始化副本集
6.1 在 Primary 节点执行初始化
// 连接到计划作为 Primary 的节点
mongosh "[IP1]:27017"
// 初始化副本集,指定所有成员
rs.initiate({
_id: "rs0",
members: [
{ _id: 0, host: "[IP1]:27017", priority: 2 },
{ _id: 1, host: "[IP2]:27017", priority: 1 },
{ _id: 2, host: "[IP3]:27017", arbiterOnly: true }
]
})
参数说明:
参数 说明 _id副本集名称,必须与 replSetName一致members[]._id成员 ID,每个成员唯一 members[].host成员地址 IP:端口members[].priority选举优先级,值越大越容易被选为主节点,范围 0~1000 members[].arbiterOnlytrue= 仲裁节点,不存储数据
6.2 查看副本集配置
// 查看配置
rs.conf()
// 查看状态(重要!)
rs.status()
rs.conf() 输出示例:
{
"_id": "rs0",
"version": 1,
"term": 1,
"protocolVersion": Long("1"),
"writeConcernMajorityJournalDefault": true,
"members": [
{
"_id": 0,
"host": "[IP1]:27017",
"arbiterOnly": false,
"buildIndexes": true,
"hidden": false,
"priority": 2,
"votes": 1
},
{
"_id": 1,
"host": "[IP2]:27017",
"arbiterOnly": false,
"buildIndexes": true,
"hidden": false,
"priority": 1,
"votes": 1
},
{
"_id": 2,
"host": "[IP3]:27017",
"arbiterOnly": true,
"priority": 0,
"votes": 1
}
],
"settings": {
"chainingAllowed": true,
"heartbeatIntervalMillis": 2000,
"heartbeatTimeoutSecs": 10,
"electionTimeoutMillis": 10000
}
}
七、验证副本集数据同步
7.1 主节点写入测试数据
// 连接到 Primary
mongosh "[IP1]:27017"
use testdb
db.users.insertOne({ name: "Alice", age: 30, role: "DBA" })
db.users.insertOne({ name: "Bob", age: 25, role: "Dev" })
db.users.find()
7.2 从节点验证数据同步
// 连接到 Secondary
mongosh "[IP2]:27017"
// MongoDB 5.0+ 使用 db.getMongo().setReadPref('secondaryPreferred')
// 或在连接时指定读偏好
mongosh "[IP2]:27017" --readPreference secondaryPreferred
use testdb
db.users.find()
⚠️ 版本差异说明:
- MongoDB 4.4:
rs.secondaryOk()允许从节点执行读操作- MongoDB 5.0+:
rs.secondaryOk()已废弃,使用读偏好(Read Preference)替代- 推荐在连接时指定:
mongosh "[IP2]:27017" --readPreference secondary
7.3 仲裁节点验证
// 仲裁节点不存储数据,仅参与选举
mongosh "[IP3]:27017"
// 仲裁节点的 rs.status() 中 stateStr 为 "ARBITER"
rs.status()
八、故障转移测试
8.1 测试场景一:Secondary 宕机
# 在 Secondary 节点执行
kill -2 $(pgrep mongod)
# 在 Primary 节点查看状态
mongosh "[IP1]:27017"
rs.status()
# 观察 members[1].stateStr 变为 "(not reachable/healthy)"
恢复 Secondary:
su - mongodb
mongod -f /mongodb/apps/mongodb/bin/mongod.conf
# 验证数据已自动同步
mongosh "[IP2]:27017" --readPreference secondary
use testdb
db.users.find()
8.2 测试场景二:Primary 宕机(自动故障转移)
# 在原 Primary 节点执行
kill -2 $(pgrep mongod)
# 在 Secondary 节点查看状态(应自动变为主节点)
mongosh "[IP2]:27017"
rs.status()
// 观察 members[1].stateStr 变为 "PRIMARY"
原 Primary 恢复后验证:
# 重启原 Primary
su - mongodb
mongod -f /mongodb/apps/mongodb/bin/mongod.conf
# 原 Primary 会自动以 Secondary 身份重新加入集群
mongosh "[IP1]:27017"
rs.status()
// 观察 members[0].stateStr 变为 "SECONDARY"
⚠️ 重要:MongoDB 8.0 对
w: "majority"的语义进行了优化——写操作只需等待多数节点写入 oplog 即可返回确认(之前还需等待 apply),写性能显著提升。
九、常用运维命令
// 查看副本集状态
rs.status()
// 查看副本集配置
rs.conf()
// 查看主从角色
rs.isMaster()
// 或
db.hello() // MongoDB 5.0+ 推荐,替代 rs.isMaster()
// 查看 oplog 状态
db.getReplicationInfo()
// 查看从节点同步延迟
db.printSlaveReplicationInfo()
// 手动降主(维护前使用)
rs.stepDown(60) // 60 秒内不会重新当选为主
// 添加新节点(扩容时使用)
rs.add("[IP4]:27017")
// 移除节点
rs.remove("[IP4]:27017")
十、总结 & 注意事项
核心要点
- 副本集核心原理:通过
local库下的oplog.rs集合实现数据同步,主节点写入 oplog,从节点异步拉取并重放 - 自动故障转移:主节点宕机后,存活节点在
electionTimeoutMillis(默认 10 秒)内发起选举,选出新主 - 奇数节点原则:副本集节点数应为奇数,确保能形成多数派,避免脑裂
- 仲裁节点作用:不存储数据,仅参与选举投票,适合资源受限环境
生产环境注意事项
| 注意事项 | 说明 |
|---|---|
| 开启认证 | 初始部署后用 security.keyFile 或 security.clusterAuthMode 开启成员间认证 |
| 绑定 IP 安全 | 绑定公网 IP 前必须启用认证,并配置防火墙规则 |
| oplog 大小 | 根据业务写入量设置,确保从节点有足够时间同步 |
| 连接字符串 | 应用使用副本集连接字符串:mongodb://[IP1]:27017,[IP2]:27017,[IP3]:27017/?replicaSet=rs0 |
| 备份策略 | 使用 mongodump 定期备份,或从隐藏节点做物理备份 |
| 版本选择 | 推荐使用 MongoDB 8.0.x 最新补丁版,避免使用 8.0.0~8.0.4 早期版本 |
版本升级路径
MongoDB 4.4 → 5.0 → 6.0 → 7.0 → 8.0
(必须逐版本升级,不可跨版本直接升级)
本文基于 MongoDB 官方文档及生产实践经验整理,适用于 MongoDB 8.0/8.3 版本。




