暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MongoDB 副本集(Replica Set)部署

原创 lucky、糯米汤圆 2026-05-11
219

适用版本: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:使用旧式配置文件格式(键值对),mongo shell
  • 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.logAppend true = 重启时追加,不覆盖
processManagement.fork true = 后台守护进程方式运行
net.bindIp 绑定 IP,逗号分隔,生产环境绑定具体 IP 而非 0.0.0.0
net.maxIncomingConnections 最大并发连接数,默认 65536
storage.dbPath 数据文件存放路径
storage.journal.enabled 开启 journal 保证宕机安全
storage.directoryPerDB true = 每个数据库独立子目录
replication.replSetName 副本集名称,所有节点必须一致
replication.oplogSizeMB oplog 大小,默认 5% 磁盘空间
security.authorization disabled = 关闭认证(初始部署用),生产环境改为 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 及之前:使用 mongo shell
  • 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[].arbiterOnly true = 仲裁节点,不存储数据

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")

十、总结 & 注意事项

核心要点

  1. 副本集核心原理:通过 local 库下的 oplog.rs 集合实现数据同步,主节点写入 oplog,从节点异步拉取并重放
  2. 自动故障转移:主节点宕机后,存活节点在 electionTimeoutMillis(默认 10 秒)内发起选举,选出新主
  3. 奇数节点原则:副本集节点数应为奇数,确保能形成多数派,避免脑裂
  4. 仲裁节点作用:不存储数据,仅参与选举投票,适合资源受限环境

生产环境注意事项

注意事项 说明
开启认证 初始部署后用 security.keyFilesecurity.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 版本。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论