一、引言:为什么选择三节点复制集?
MongoDB三节点复制集是企业级部署的最小高可用配置,提供以下关键价值:
- 自动故障转移:主节点故障时,10-30秒内自动切换
- 数据冗余:数据自动复制到所有节点
- 读扩展性:从节点可处理读请求
- 灾难恢复:保障业务连续性
- 成本效益:平衡高可用性与资源消耗
关键洞察:三节点复制集(1 Primary + 2 Secondary)是避免脑裂问题的最小配置,比两节点方案更可靠,比五节点方案更经济。
二、环境准备
2.1 硬件要求
| 组件 | 最低配置 | 推荐配置 |
|---|---|---|
| CPU | 2核 | 4核+ |
| 内存 | 4GB | 8GB+ |
| 存储 | 50GB | 200GB+ |
| 网络 | 1Gbps | 1Gbps+ |
注意事项:
- 三台服务器应有相同规格(避免性能瓶颈)
- 存储应使用SSD(HDD仅适用于测试环境)
- 网络延迟应**< 5ms**(同机房部署)
2.2 软件环境
| 组件 | 版本 | 说明 |
|---|---|---|
| 操作系统 | CentOS 7.9+ / Ubuntu 20.04+ | 保持一致 |
| MongoDB | 6.0+ | 稳定版本 |
| 防火墙 | 开放27017端口 | 节点间通信 |
| SELinux/AppArmor | 禁用或配置 | 避免权限问题 |
2.3 网络规划
| 节点 | 主机名 | IP地址 | 角色 |
|---|---|---|---|
| 节点1 | mongo1 | 192.168.1.10 | Primary |
| 节点2 | mongo2 | 192.168.1.11 | Secondary |
| 节点3 | mongo3 | 192.168.1.12 | Secondary |
关键配置:
- 所有节点需在
/etc/hosts中配置相互解析 - 禁用IPv6(避免连接问题)
- 配置NTP时间同步
2.3.1 hosts文件配置(所有节点)
bash
# 编辑hosts文件
sudo vi /etc/hosts
# 添加以下内容
192.168.1.10 mongo1
192.168.1.11 mongo2
192.168.1.12 mongo3
2.3.2 时间同步配置
bash
# 安装NTP服务
sudo yum install -y ntp # CentOS
sudo apt-get install -y ntp # Ubuntu
# 启动并设置开机启动
sudo systemctl enable ntpd
sudo systemctl start ntpd
# 检查同步状态
ntpq -p
三、MongoDB安装
3.1 添加MongoDB仓库
3.1.1 CentOS
bash
# 创建MongoDB仓库文件
sudo vi /etc/yum.repos.d/mongodb-org-6.0.repo
# 添加以下内容
[mongodb-org-6.0]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/6.0/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-6.0.asc
3.1.2 Ubuntu
bash
# 导入GPG密钥
wget -qO - https://www.mongodb.org/static/pgp/server-6.0.asc | sudo apt-key add -
# 添加仓库
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu $(lsb_release -cs)/mongodb-org/6.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-6.0.list
# 更新包列表
sudo apt update
3.2 安装MongoDB
3.2.1 CentOS
bash
sudo yum install -y mongodb-org
3.2.2 Ubuntu
bash
sudo apt install -y mongodb-org
3.3 验证安装
bash
# 检查MongoDB版本
mongod --version
# 输出应包含
# db version v6.0.x
# git version: ...
四、配置复制集
4.1 创建数据目录
所有节点执行:
bash
sudo mkdir -p /var/lib/mongodb
sudo mkdir -p /var/log/mongodb
sudo chown -R mongod:mongod /var/lib/mongodb /var/log/mongodb
4.2 配置文件设置
所有节点执行:
bash
sudo vi /etc/mongod.conf
配置内容:
yaml
# 网络配置
net:
port: 27017
bindIp: 0.0.0.0 # 允许所有IP连接(生产环境应限制IP)
# 存储配置
storage:
dbPath: /var/lib/mongodb
journal:
enabled: true
# 复制集配置
replication:
replSetName: rs0 # 复制集名称,所有节点必须相同
# 安全配置
security:
authorization: disabled # 生产环境应启用
# 服务配置
processManagement:
timeZoneInfo: /usr/share/zoneinfo
关键说明:
replSetName:必须在所有节点配置相同bindIp:测试环境可设为0.0.0.0,生产环境应限制authorization:生产环境应启用,此处为简化步骤
4.3 防火墙配置
所有节点执行:
bash
# CentOS
sudo firewall-cmd --zone=public --add-port=27017/tcp --permanent
sudo firewall-cmd --reload
# Ubuntu
sudo ufw allow 27017/tcp
五、启动服务并初始化复制集
5.1 启动MongoDB服务
所有节点执行:
bash
sudo systemctl enable mongod
sudo systemctl start mongod
验证服务状态:
bash
sudo systemctl status mongod
5.2 初始化复制集
5.2.1 连接Primary节点
bash
mongo --host mongo1
5.2.2 初始化复制集配置
javascript
// 创建复制集配置
cfg = {
_id: "rs0",
members: [
{ _id: 0, host: "mongo1:27017" },
{ _id: 1, host: "mongo2:27017" },
{ _id: 2, host: "mongo3:27017" }
]
};
// 初始化复制集
rs.initiate(cfg);
// 检查状态
rs.status();
预期输出:
{
"set" : "rs0",
"date" : ISODate("..."),
"myState" : 1,
"members" : [
{
"_id" : 0,
"name" : "mongo1:27017",
"state" : 1,
"stateStr" : "PRIMARY",
...
},
{
"_id" : 1,
"name" : "mongo2:27017",
"state" : 2,
"stateStr" : "SECONDARY",
...
},
{
"_id" : 2,
"name" : "mongo3:27017",
"state" : 2,
"stateStr" : "SECONDARY",
...
}
],
...
}
5.3 验证数据同步
5.3.1 写入测试数据
javascript
// 连接Primary
mongo --host mongo1
// 写入数据
use test
db.test.insertOne({ name: "MongoDB", version: "6.0" })
5.3.2 验证同步
javascript
// 连接Secondary
mongo --host mongo2
// 检查数据
use test
db.test.find()
预期输出:
javascript
{ "_id" : ObjectId("..."), "name" : "MongoDB", "version" : "6.0" }
六、基础运维操作
6.1 检查复制集状态
javascript
rs.status()
关键字段解读:
stateStr:节点状态(PRIMARY/SECONDARY)optime:最新操作时间syncSourceHost:同步源节点health:节点健康状态(1=健康)
6.2 读写偏好配置
6.2.1 从Secondary读取
javascript
// 连接时指定
mongo --host "mongo2,mongo3" --readPreference=secondary
// 应用代码中
const client = new MongoClient(
"mongodb://mongo2,mongo3",
{ readPreference: "secondary" }
);
6.2.2 强制Primary读取
javascript
// 连接时指定
mongo --host "mongo1,mongo2,mongo3" --readPreference=primary
// 应用代码中
const client = new MongoClient(
"mongodb://mongo1,mongo2,mongo3",
{ readPreference: "primary" }
);
6.3 手动主从切换
6.3.1 降级Primary
javascript
// 在Primary执行
rs.stepDown(60, 15)
- 60:降级持续时间(秒)
- 15:等待Secondary追赶时间(秒)
6.3.2 验证切换
javascript
// 检查状态
rs.status()
预期结果:原Primary变为SECONDARY,其他节点中一个变为PRIMARY
6.4 添加/移除节点
6.4.1 添加新节点
javascript
// 连接Primary
rs.add("mongo4:27017")
6.4.2 移除节点
javascript
// 连接Primary
rs.remove("mongo3:27017")
七、监控与故障排查
7.1 关键监控指标
| 指标 | 监控命令 | 健康阈值 | 告警阈值 |
|---|---|---|---|
| 节点状态 | rs.status() |
PRIMARY/SECONDARY | DOWN/UNKNOWN |
| 复制延迟 | rs.printSlaveReplicationInfo() |
< 30秒 | > 60秒 |
| Oplog状态 | rs.printReplicationInfo() |
> 20%剩余 | < 10%剩余 |
| 网络延迟 | db.adminCommand({ping: 1}) |
< 5ms | > 100ms |
| 选举次数 | 日志分析 | 每日<1次 | 每日>5次 |
7.2 监控脚本示例
javascript
function monitorReplicaSet() {
const status = rs.status();
const primary = status.members.find(m => m.state === 1);
// 检查异常状态
status.members.forEach(member => {
if (member.state === 0 || member.state === 3 || member.state === 4) {
console.log(`CRITICAL: Node ${member.name} in abnormal state (${member.stateStr})`);
}
});
// 检查复制延迟
status.members.forEach(member => {
if (member.state === 2) {
const lag = primary.optimeDate - member.optimeDate;
if (lag > 60000) {
console.log(`WARNING: High replication lag on ${member.name} (${lag}ms)`);
}
}
});
}
// 定时执行
setInterval(monitorReplicaSet, 60000); // 每分钟
7.3 常见问题排查
7.3.1 节点状态为DOWN
原因:
- 网络不通
- 服务未启动
- 防火墙限制
解决方案:
bash
# 检查网络连通性
ping mongo2
# 检查服务状态
systemctl status mongod
# 检查防火墙
firewall-cmd --list-all | grep 27017
7.3.2 复制延迟过高
原因:
- 网络带宽不足
- Secondary资源不足
- 大量写操作
解决方案:
javascript
// 检查复制延迟
rs.printSlaveReplicationInfo()
// 检查Oplog大小
rs.printReplicationInfo()
// 增加Oplog大小(需重启)
db.adminCommand({ replSetResizeOplog: 1, size: 4096 }) // 4GB
7.3.3 选举失败
原因:
- 无法形成"大多数"
- 网络分区
- 配置不一致
解决方案:
javascript
// 检查复制集配置
rs.conf()
// 检查节点状态
rs.status().members.forEach(m => {
console.log(`Node: ${m.name}, State: ${m.stateStr}`);
});
// 重新配置复制集
cfg = rs.conf();
// 修改配置
rs.reconfig(cfg);
八、生产环境最佳实践
8.1 安全配置
8.1.1 启用认证
yaml
# 修改/etc/mongod.conf
security:
authorization: enabled
8.1.2 创建管理员用户
javascript
// 连接Primary
mongo --host mongo1
// 创建管理员用户
use admin
db.createUser({
user: "admin",
pwd: "password",
roles: ["root"]
});
8.1.3 配置TLS/SSL
yaml
net:
tls:
mode: requireTLS
certificateKeyFile: /etc/ssl/mongodb.pem
8.2 备份策略
8.2.1 逻辑备份
bash
# 备份所有数据库
mongodump --uri="mongodb://admin:password@mongo1:27017" --out /backup/$(date +%Y%m%d)
8.2.2 物理备份
bash
# 停止MongoDB
sudo systemctl stop mongod
# 备份数据目录
tar -czvf /backup/mongodb-data-$(date +%Y%m%d).tar.gz /var/lib/mongodb
# 重启MongoDB
sudo systemctl start mongod
8.3 定期维护
| 操作 | 频率 | 说明 |
|---|---|---|
| Oplog大小检查 | 每周 | 确保足够空间 |
| 备份验证 | 每月 | 恢复测试 |
| 滚动升级 | 每季度 | 无停机升级 |
| 故障演练 | 每半年 | 验证恢复能力 |
九、案例:模拟故障转移
9.1 模拟Primary故障
bash
# 停止Primary节点
sudo systemctl stop mongod
9.2 监控自动故障转移
javascript
// 在Secondary节点执行
rs.status().members.forEach(m => {
console.log(`Node: ${m.name}, State: ${m.stateStr}`);
});
预期输出:
Node: mongo1:27017, State: DOWN
Node: mongo2:27017, State: PRIMARY
Node: mongo3:27017, State: SECONDARY
9.3 验证服务连续性
javascript
# 从应用连接
mongo --host mongo2 --eval "db.test.find()"
# 预期输出
{ "_id" : ObjectId("..."), "name" : "MongoDB", "version" : "6.0" }
十、总结:三节点复制集的实施要点
10.1 成功实施的关键因素
| 因素 | 说明 | 重要性 |
|---|---|---|
| 奇数节点 | 3、5、7节点配置 | ★★★★★ |
| 网络配置 | 稳定的低延迟网络 | ★★★★☆ |
| Oplog大小 | 保证足够空间 | ★★★★☆ |
| 监控体系 | 实时监控关键指标 | ★★★★☆ |
| 定期演练 | 模拟故障转移 | ★★★★☆ |
10.2 实施路线图
| 阶段 | 目标 | 操作 |
|---|---|---|
| 评估 | 确认需求 | 分析业务SLA要求 |
| 规划 | 设计架构 | 确定节点数量和拓扑 |
| 实施 | 部署集群 | 按本指南步骤执行 |
| 验证 | 测试功能 | 模拟故障转移 |
| 监控 | 持续跟踪 | 设置告警阈值 |
| 优化 | 持续改进 | 根据业务增长调整 |
10.3 最终建议
- 从简单开始:先部署最小可行方案
- 文档化一切:记录所有配置和操作
- 先测试后生产:在非生产环境验证
- 安全优先:启用认证和加密
- 持续学习:关注MongoDB新特性
关键结论 :三节点MongoDB复制集是企业级高可用数据库的基础。通过本指南的详细步骤,您可以快速部署一个可靠的复制集集群,为业务提供坚实的数据保障。记住,高可用性不是一次性的配置任务,而是一个持续优化的过程。定期监控、测试和优化您的复制集,确保它始终符合业务需求。
下一步行动:
- 在测试环境部署三节点集群
- 执行故障转移演练
- 实施监控告警系统
- 制定定期维护计划
通过这些步骤,您将拥有一个稳定、可靠、高性能的MongoDB复制集。