跳到主要内容

第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