第3章 MongoDB副本集
副本集概述
MongoDB副本集(Replica Set)是一组维护相同数据集的MongoDB服务实例,提供数据冗余和高可用性。副本集是MongoDB生产部署的基础,通过数据复制和自动故障转移来确保服务的连续性。
核心概念
副本集(Replica Set):由多个MongoDB实例组成的集群,其中一个作为主节点,其他作为从节点。
Oplog:操作日志,记录主节点上的所有写操作,从节点通过复制oplog来保持数据同步。
选举(Election):当主节点不可用时,从节点通过投票选出新的主节点的过程。
主要优势
- 高可用性:主节点故障时自动切换到从节点
- 数据冗余:多个节点保存相同数据,防止数据丢失
- 读写分离:可配置从节点提供读操作,分担主节点压力
- 零停机维护:可在不停机的情况下进行节点维护
📚 复制原理
主节点接收所有写操作并记录到oplog中,从节点定期从主节点拉取oplog并应用这些操作,从而保持数据同步。
副本集架构设计
节点角色类型
节点类型 | 功能描述 | 数据存储 | 参与选举 | 适用场景 |
---|---|---|---|---|
主节点(Primary) | 处理所有写操作和读操作 | ✅ | ✅ | 核心数据处理 |
从节点(Secondary) | 同步主节点数据,可提供读操作 | ✅ | ✅ | 数据备份、读负载分担 |
仲裁节点(Arbiter) | 仅参与选举投票 | ❌ | ✅ | 提供奇数投票,节省资源 |
选举机制
副本集采用大多数投票原则进行主节点选举:
- 存活节点数量必须超过副本集总节点数的一半
- 具有最新数据且优先级最高的节点当选为主节点
- 选举过程通常在几秒钟内完成
⚠️ 节点数量建议
生产环境建议使用奇数个节点(如3、5、7个),避免出现平票情况。最少需要3个节点才能保证高可用性。
架构规划示例
3节点标准配置:
- 1个主节点 + 2个从节点
- 允许1个节点故障
- 适合大多数生产环境
5节点高可用配置:
- 1个主节点 + 4个从节点
- 允许2个节点故障
- 适合关键业务系统
仲裁节点配置:
- 2个数据节点 + 1个仲裁节点
- 节省存储资源
- 适合资源受限环境
副本集部署配置
环境准备
# 创建副本集目录结构
mkdir -p /opt/mongo_2801{7,8,9}/{conf,log,pid}
mkdir -p /data/mongo_2801{7,8,9}
# 设置目录权限
chown -R mongo:mongo /opt/mongo_28*
chown -R mongo:mongo /data/mongo_28*
主节点配置
# 创建主节点配置文件
cat > /opt/mongo_28017/conf/mongodb.conf << EOF
systemLog:
destination: file
logAppend: true
path: /opt/mongo_28017/log/mongodb.log
storage:
journal:
enabled: true
dbPath: /data/mongo_28017
directoryPerDB: true
wiredTiger:
engineConfig:
cacheSizeGB: 0.5
directoryForIndexes: true
collectionConfig:
blockCompressor: zlib
indexConfig:
prefixCompression: true
processManagement:
fork: true
pidFilePath: /opt/mongo_28017/pid/mongod.pid
net:
port: 28017
bindIp: 127.0.0.1,10.0.0.51
replication:
oplogSizeMB: 1024
replSetName: dba
EOF
从节点配置
# 复制配置文件到其他节点
cp /opt/mongo_28017/conf/mongodb.conf /opt/mongo_28018/conf/
cp /opt/mongo_28017/conf/mongodb.conf /opt/mongo_28019/conf/
# 修改端口号和路径
sed -i 's/28017/28018/g' /opt/mongo_28018/conf/mongodb.conf
sed -i 's/28017/28019/g' /opt/mongo_28019/conf/mongodb.conf
配置参数说明
replication配置项:
oplogSizeMB
:oplog大小,建议设置为磁盘空间的5-10%replSetName
:副本集名称,所有节点必须相同
💡 生产环境配置建议
- oplog大小应根据写操作频率调整,确保从节点有足够时间同步
- 绑定IP应包括所有副本集成员可访问的地址
- 建议启用访问控制和SSL加密
副本集初始化
启动所有节点
# 启动三个MongoDB实例
mongod -f /opt/mongo_28017/conf/mongodb.conf
mongod -f /opt/mongo_28018/conf/mongodb.conf
mongod -f /opt/mongo_28019/conf/mongodb.conf
# 验证服务启动
ps -ef | grep mongod
netstat -lntup | grep -E "2801[789]"
初始化副本集
// 连接到主节点
mongo --port 28017
// 初始化副本集配置
rs.initiate({
_id: "dba",
version: 1,
members: [
{ _id: 0, host: "10.0.0.51:28017" },
{ _id: 1, host: "10.0.0.51:28018" },
{ _id: 2, host: "10.0.0.51:28019" }
]
})
// 查看副本集状态
rs.status()
验证副本集状态
// 检查副本集配置
rs.config()
// 确认当前节点角色
rs.isMaster()
// 查看复制信息
rs.printReplicationInfo()
rs.printSlaveReplicationInfo()
📋 初始化完成标志
当看到提示符变为 dba:PRIMARY>
或 dba:SECONDARY>
时,表示副本集初始化成功。
故障转移和选举
数据同步测试
// 在主节点插入测试数据
mongo --port 28017
db.inventory.insertMany([
{ item: "journal", qty: 25, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
{ item: "notebook", qty: 50, size: { h: 8.5, w: 11, uom: "in" }, status: "A" },
{ item: "paper", qty: 100, size: { h: 8.5, w: 11, uom: "in" }, status: "D" },
{ item: "planner", qty: 75, size: { h: 22.85, w: 30, uom: "cm" }, status: "D" },
{ item: "postcard", qty: 45, size: { h: 10, w: 15.25, uom: "cm" }, status: "A" }
])
配置从节点读取
// 连接到从节点
mongo --port 28018
// 允许从节点读取(临时)
rs.slaveOk()
// 验证数据同步
db.inventory.find()
永久设置从节点可读:
# 创建MongoDB启动脚本
echo "rs.slaveOk()" > ~/.mongorc.js
故障转移测试
# 模拟主节点故障
mongod -f /opt/mongo_28017/conf/mongodb.conf --shutdown
# 连接到从节点观察选举过程
mongo --port 28018
rs.status()
⚠️ 故障转移注意事项
主节点故障时,客户端连接会短暂中断。应用程序应该实现重连机制来处理这种情况。
优先级调整
// 获取当前配置
myconfig = rs.conf()
// 设置节点优先级(数值越高优先级越高)
myconfig.members[0].priority = 100
myconfig.members[1].priority = 50
myconfig.members[2].priority = 25
// 应用新配置
rs.reconfig(myconfig)
手动切换主节点
// 主动降级当前主节点
rs.stepDown(60) // 60秒内不参与选举
副本集管理操作
动态添加节点
# 创建新节点
mkdir -p /opt/mongo_28010/{conf,log,pid}
mkdir -p /data/mongo_28010
# 复制配置文件
cp /opt/mongo_28017/conf/mongodb.conf /opt/mongo_28010/conf/
sed -i 's/28017/28010/g' /opt/mongo_28010/conf/mongodb.conf
# 启动新节点
mongod -f /opt/mongo_28010/conf/mongodb.conf
// 将新节点加入副本集
rs.add("10.0.0.51:28010")
// 验证节点状态
rs.status()
移除节点
// 从副本集中移除节点
rs.remove("10.0.0.51:28010")
// 确认移除结果
rs.config()
仲裁节点管理
# 创建仲裁节点
mkdir -p /opt/mongo_28011/{conf,log,pid}
mkdir -p /data/mongo_28011
cp /opt/mongo_28017/conf/mongodb.conf /opt/mongo_28011/conf/
sed -i 's/28017/28011/g' /opt/mongo_28011/conf/mongodb.conf
# 启动仲裁节点
mongod -f /opt/mongo_28011/conf/mongodb.conf
// 添加仲裁节点
rs.addArb("10.0.0.51:28011")
// 验证仲裁节点状态
rs.status()
💡 仲裁节点使用建议
- 仲裁节点不存储数据,资源消耗很小
- 建议部署在独立的服务器上以提高可靠性
- 一个副本集最多只能有一个仲裁节点
监控和维护
副本集状态监控
// 常用监控命令
rs.status() // 副本集整体状态
rs.config() // 副本集配置信息
rs.isMaster() // 当前节点角色
rs.printReplicationInfo() // 主节点复制信息
rs.printSlaveReplicationInfo() // 从节点复制信息
关键监控指标
指标 | 命令 | 说明 |
---|---|---|
复制延迟 | rs.printSlaveReplicationInfo() | 从节点与主节点的数据延迟 |
Oplog窗口 | rs.printReplicationInfo() | oplog可覆盖的时间范围 |
节点健康状态 | rs.status().members[].health | 节点健康度(1为正常) |
选举状态 | rs.status().members[].stateStr | 节点角色状态 |
性能优化建议
💡 生产环境最佳实践
硬件配置:
- 主节点和从节点使用相同或相近的硬件配置
- 保证足够的内存用于缓存工作集
- 使用SSD存储以提高IO性能
网络配置:
- 副本集成员间使用低延迟网络连接
- 监控网络带宽使用情况
- 配置适当的心跳超时参数
运维策略:
- 定期检查oplog大小是否充足
- 监控复制延迟,及时处理同步问题
- 建立自动化的健康检查和告警机制
故障排查指南
常见问题及解决方案:
节点无法同步:
- 检查网络连接和防火墙设置
- 验证副本集配置中的主机名和端口
- 确认oplog空间是否充足
选举失败:
- 确认存活节点数量是否满足大多数原则
- 检查节点间的网络连通性
- 验证系统时间是否同步
复制延迟过高:
- 检查主节点的写入压力
- 优化查询和索引
- 考虑增加从节点数量分担负载
容灾和备份
# 副本集容灾能力
echo "副本集容灾能力:"
echo "3节点副本集:允许1个节点故障"
echo "5节点副本集:允许2个节点故障"
echo "4节点+1仲裁:允许2个数据节点故障"
⚠️ 备份策略提醒
副本集虽然提供数据冗余,但不能替代定期备份。建议:
- 定期对副本集进行完整备份
- 测试备份恢复流程
- 考虑跨地域的灾备方案
📖 参考资源
更新: 2025-01-26