Skip to content

MongoDB 副本集配置

副本集初始化

1. 环境准备

硬件要求

  • 至少3个节点(推荐奇数个节点,如3、5个)
  • 每个节点至少4GB RAM,50GB磁盘空间
  • 节点间网络延迟低(< 10ms)
  • 相同的硬件配置和MongoDB版本

软件要求

  • MongoDB 3.6+ 版本
  • 操作系统:Linux、Windows Server、macOS
  • 关闭防火墙或开放必要端口(默认27017)

2. 配置文件设置

基本配置文件(mongod.conf)

yaml
# 基本设置
net:
  port: 27017
  bindIp: 0.0.0.0

dbPath: /data/db

# 安全设置
security:
  keyFile: /etc/mongodb/keyfile
  authorization: enabled

# 副本集设置
replication:
  replSetName: rs0
  oplogSizeMB: 10240
  enableMajorityReadConcern: true

# 存储引擎设置
storage:
  engine: wiredTiger
  wiredTiger:
    engineConfig:
      cacheSizeGB: 4
      directoryForIndexes: true
    collectionConfig:
      blockCompressor: zstd

# 日志设置
systemLog:
  destination: file
  path: /var/log/mongodb/mongod.log
  logAppend: true
  logRotate: reopen

3. 生成keyFile

bash
# 生成keyFile
openssl rand -base64 756 > /etc/mongodb/keyfile

# 设置权限
chmod 400 /etc/mongodb/keyfile

# 复制到所有节点
sudo scp /etc/mongodb/keyfile user@node2:/etc/mongodb/
sudo scp /etc/mongodb/keyfile user@node3:/etc/mongodb/

4. 初始化副本集

启动所有节点

bash
sudo systemctl start mongod

连接到第一个节点

bash
mongo --host node1:27017

初始化副本集配置

javascript
rs.initiate({
  _id: "rs0",
  members: [
    { _id: 0, host: "node1:27017", priority: 1, votes: 1 },
    { _id: 1, host: "node2:27017", priority: 1, votes: 1 },
    { _id: 2, host: "node3:27017", priority: 1, votes: 1 }
  ]
})

验证初始化结果

javascript
rs.status()

副本集成员管理

1. 添加副本集成员

添加常规副本成员

javascript
rs.add({
  host: "node4:27017",
  priority: 1,
  votes: 1
})

添加仲裁者

javascript
rs.add({
  host: "node5:27017",
  arbiterOnly: true
})

添加隐藏成员

javascript
rs.add({
  host: "node6:27017",
  priority: 0,
  votes: 0,
  hidden: true,
  secondaryDelaySecs: 3600
})

2. 移除副本集成员

移除成员

javascript
rs.remove("node4:27017")

3. 修改成员配置

修改成员优先级

javascript
var cfg = rs.conf()
cfg.members[0].priority = 2
cfg.members[1].priority = 0.5
rs.reconfig(cfg)

修改投票权

javascript
var cfg = rs.conf()
cfg.members[2].votes = 0
rs.reconfig(cfg)

添加标签

javascript
var cfg = rs.conf()
cfg.members[0].tags = { "dc": "us-east-1", "role": "primary" }
cfg.members[1].tags = { "dc": "us-east-1", "role": "secondary" }
cfg.members[2].tags = { "dc": "us-west-2", "role": "secondary" }
rs.reconfig(cfg)

副本集参数配置

1. Oplog配置

查看当前oplog大小

javascript
db.oplog.rs.stats().maxSize

调整oplog大小

javascript
// 停止节点
// 备份当前oplog
mongodump --db local --collection oplog.rs --out /backup

// 启动节点(使用--oplogSizeMB参数)
mongod --replSet rs0 --oplogSizeMB 20480

// 恢复oplog
mongorestore --db local --collection oplog.rs /backup/local/oplog.rs.bson

// 重启节点

2. 读取关注点配置

设置默认读取关注点

yaml
replication:
  enableMajorityReadConcern: true

setParameter:
  defaultReadConcern: "majority"

3. 选举配置

调整选举超时时间

yaml
replication:
  electionTimeoutMillis: 10000  # 10秒

调整心跳间隔

yaml
replication:
  heartbeatIntervalMillis: 2000  # 2秒

4. 复制延迟配置

设置延迟节点

javascript
var cfg = rs.conf()
cfg.members[2].secondaryDelaySecs = 7200  # 2小时
rs.reconfig(cfg)

副本集高级配置

1. 读写分离配置

配置读取偏好

yaml
# 客户端连接字符串示例
mongodb://user:password@node1:27017,node2:27017,node3:27017/?replicaSet=rs0&readPreference=secondary

读取偏好类型

  • primary:只从主节点读取(默认)
  • primaryPreferred:优先从主节点读取,主节点不可用时从副本节点读取
  • secondary:只从副本节点读取
  • secondaryPreferred:优先从副本节点读取,副本节点不可用时从主节点读取
  • nearest:从网络延迟最低的节点读取

2. 地理位置感知配置

配置区域标签

javascript
var cfg = rs.conf()
cfg.members[0].tags = { "region": "us-east-1" }
cfg.members[1].tags = { "region": "us-east-1" }
cfg.members[2].tags = { "region": "us-west-2" }
rs.reconfig(cfg)

配置区域写入关注点

yaml
replication:
  replicaSetName: rs0
  writeConcernMajorityJournalDefault: true
  enableMajorityReadConcern: true
  tags: [
    { "name": "region-us-east-1", "region": "us-east-1" },
    { "name": "region-us-west-2", "region": "us-west-2" }
  ]

3. TLS/SSL配置

副本集TLS配置

yaml
net:
  tls:
    mode: requireTLS
    certificateKeyFile: /etc/mongodb/mongodb.pem
    CAFile: /etc/mongodb/ca.crt
    clusterFile: /etc/mongodb/mongodb.pem
    allowInvalidHostnames: false
    allowInvalidCertificates: false

4. 认证配置

启用SCRAM认证

javascript
// 创建管理员用户
use admin
db.createUser({
  user: "admin",
  pwd: "password",
  roles: [{ role: "root", db: "admin" }]
})

配置用户角色

javascript
// 创建副本集管理用户
use admin
db.createUser({
  user: "replicaAdmin",
  pwd: "password",
  roles: [{ role: "clusterAdmin", db: "admin" }]
})

副本集监控与维护

1. 监控副本集状态

查看副本集状态

javascript
rs.status()

查看成员状态

javascript
rs.status().members.forEach(member => {
  print(`${member.name}: ${member.stateStr}, ${member.replicationLag || 0}ms`)
})

查看复制延迟

javascript
rs.printSlaveReplicationInfo()

2. 副本集维护操作

重新配置副本集

javascript
// 强制重新配置(用于修复配置问题)
rs.reconfig(cfg, { force: true })

冻结节点

javascript
// 冻结当前节点24小时(防止选举)
rs.freeze(86400)

步进节点

javascript
// 将当前主节点步进为从节点
rs.stepDown()

3. 备份与恢复

备份副本集

bash
# 从副本节点备份
mongodump --host node2:27017 --oplog --out /backup/replset_backup

恢复副本集

bash
# 停止所有节点
# 清空数据目录
rm -rf /data/db/*

# 从备份恢复
mongorestore --oplogReplay /backup/replset_backup

# 重新初始化副本集

副本集最佳实践

1. 部署最佳实践

  • 使用奇数个节点:推荐3或5个节点,提供更好的高可用性
  • 分布在不同机架/可用区:避免单点故障
  • 统一硬件配置:确保节点性能一致
  • 使用相同的MongoDB版本:避免版本兼容性问题
  • 启用TLS/SSL:保护节点间通信
  • 启用认证:防止未授权访问

2. 配置最佳实践

  • 设置合适的oplog大小:至少能保存24小时的操作
  • 启用majority读取关注点:确保数据一致性
  • 配置合理的选举超时时间:平衡故障检测和误触发
  • 设置适当的心跳间隔:及时检测节点故障
  • 使用标签路由:支持地理位置感知和读写分离

3. 监控最佳实践

  • 监控复制延迟:设置告警阈值(如> 10秒)
  • 监控节点状态:及时发现节点故障
  • 监控oplog大小和利用率:确保有足够的oplog空间
  • 监控选举次数:频繁选举可能表示网络问题
  • 监控写入关注点确认时间:确保写入操作及时复制到副本节点

4. 维护最佳实践

  • 定期演练故障切换:确保副本集在故障时能正常工作
  • 定期备份oplog:用于点时间恢复
  • 定期检查配置:确保配置与最佳实践一致
  • 定期更新MongoDB版本:获取最新的功能和安全修复
  • 记录操作:所有副本集操作都应记录并审核

常见问题(FAQ)

Q1: 副本集最少需要几个节点?

A1: 副本集最少需要1个节点(单节点副本集),但生产环境推荐至少3个节点,以提供高可用性和数据冗余。

Q2: 什么是仲裁者?什么时候需要使用?

A2: 仲裁者是一个特殊的副本集成员,只参与选举投票,不存储数据。当您需要奇数个投票成员但不想增加额外的数据存储节点时,可以使用仲裁者。

Q3: 如何将单节点MongoDB转换为副本集?

A3: 转换步骤:

  1. 停止MongoDB实例
  2. 修改配置文件,添加replSetName参数
  3. 重启MongoDB实例
  4. 连接到实例,执行rs.initiate()初始化副本集
  5. 可选:添加更多副本节点

Q4: 副本集成员之间的网络延迟应该控制在多少以内?

A4: 推荐副本集成员之间的网络延迟控制在10ms以内,最大不超过50ms。高延迟会影响复制性能和选举速度。

Q5: 如何处理副本集成员不可用的情况?

A5: 处理步骤:

  1. 检查节点状态和日志,确定故障原因
  2. 修复故障节点,重启MongoDB实例
  3. 等待节点重新加入副本集并同步数据
  4. 如果节点无法修复,移除该节点并添加新节点

Q6: 如何监控副本集的性能?

A6: 可以使用以下工具监控副本集性能:

  • MongoDB Atlas/Ops Manager:提供完整的监控和告警功能
  • mongostat:实时监控副本集状态
  • mongotop:监控集合级别的读写性能
  • db.serverStatus():查看服务器状态指标
  • db.hello():查看当前节点的角色和状态

Q7: 如何优化副本集的复制性能?

A7: 优化方法:

  • 使用高性能网络连接
  • 确保副本节点有足够的硬件资源
  • 调整oplog大小
  • 优化写入模式,减少大事务
  • 考虑使用分片集群分散写入负载

Q8: 副本集配置文件中的keyFile有什么作用?

A8: keyFile用于副本集成员之间的认证,确保只有持有相同keyFile的节点才能加入副本集。它是副本集安全的重要组成部分,必须严格保护。