创建副本集知识点梳理
1. 复制简介
1.1 副本集的概念
副本集(Replica Set)是MongoDB的核心高可用机制,由一组维护相同数据集的mongod实例组成,提供:
- 数据冗余:多个节点保存相同数据,防止单点故障
- 高可用性:主节点故障时自动选举新主节点
- 读写分离:读请求可分发到从节点,分担主节点压力
- 灾难恢复:从节点可切换为主节点,或用于数据恢复
1.2 副本集架构
一个标准的副本集由以下角色组成:
| 角色 | 数量 | 功能描述 |
|---|---|---|
| 主节点(Primary) | 1个 | 接收所有写操作,记录操作日志(oplog),是副本集的核心 |
| 从节点(Secondary) | 1个或多个 | 异步复制主节点的oplog并应用,可参与选举和提供读服务 |
| 仲裁节点(Arbiter) | 可选 | 不存储数据,仅参与选举投票,用于满足奇数票数要求 |
节点数量建议:
- 生产环境至少部署3个数据节点,或2个数据节点+1个仲裁节点
- 副本集节点总数应为奇数,确保选举时能获得多数票(
majority)
1.3 数据复制机制
- 异步复制:从节点通过异步方式从主节点拉取oplog并重放,默认存在秒级延迟
- 同步复制 :可通过
writeConcern: majority实现同步确认 - Oplog:主节点的操作日志,记录所有写操作,用于从节点同步和故障恢复
1.4 选举机制
当主节点不可达时,副本集触发选举:
- 选举触发条件:主节点心跳超时(默认10秒)、节点启动、手动触发
- 选举算法:基于Raft协议(MongoDB 3.2+)
- 选举因素:优先级(priority)、optime(最新操作)、网络连接
2. 建立副本集(一)
2.1 环境准备
基础配置要求:
- 至少3个节点(或2节点+仲裁者)
- 所有节点时间同步(使用NTP服务)
- 主机名可解析(使用DNS或hosts文件)
- 网络互通,防火墙开放指定端口
2.2 启动单节点实例
每个副本集成员以独立的mongod进程启动,关键配置参数:
yaml
# mongod.conf - 节点1配置
systemLog:
destination: file
path: /var/log/mongodb/mongod1.log
logAppend: true
storage:
dbPath: /data/mongodb/node1
journal:
enabled: true
net:
bindIp: 0.0.0.0
port: 27017
replication:
replSetName: "rs0" # 副本集名称,所有节点必须一致
processManagement:
fork: true
pidFilePath: /var/run/mongodb/mongod1.pid
启动命令:
bash
mongod --config /etc/mongod.conf
2.3 初始化副本集
连接到任意一个节点,执行副本集初始化:
javascript
// 连接到主节点(或任意节点)
mongo --host 192.168.1.10 --port 27017
// 定义副本集配置
rsconf = {
_id: "rs0", // 副本集名称,必须与配置一致
members: [
{ _id: 0, host: "host1:27017" },
{ _id: 1, host: "host2:27017" },
{ _id: 2, host: "host3:27017" }
]
}
// 初始化副本集
rs.initiate(rsconf)
// 查看副本集状态
rs.status()
2.4 初始化后的状态变化
- STARTUP → STARTUP2:节点启动,加载配置
- RECOVERING:恢复状态,正在应用oplog或进行数据同步
- SECONDARY:从节点,正常提供服务
- PRIMARY:主节点,选举产生
3. 网络注意事项
3.1 网络连接要求
| 项目 | 要求 | 说明 |
|---|---|---|
| 端口配置 | 所有节点端口互通 | 默认27017,可自定义 |
| 网络延迟 | < 50ms(推荐) | 高延迟影响同步效率和选举速度 |
| 带宽 | 足够传输oplog | oplog增长速率取决于写入负载 |
| 防火墙 | 开放所需端口 | 包括内部通信和客户端连接 |
| DNS解析 | 所有节点可互相解析 | 使用静态IP或内部DNS |
3.2 网络故障处理
- 心跳机制:节点间每2秒发送一次心跳,10秒未响应则标记为不可达
- 网络分区(Split Brain):通过多数选举机制防止出现多个主节点
- 自动恢复:网络恢复后,节点自动重新加入副本集并追赶oplog
3.3 网络配置最佳实践
- 使用专用网络 或VPC隔离副本集通信
- 配置hosts文件确保主机名解析正确
- 使用多个网络接口分离客户端流量和副本集内部流量
- 配置TCP keepalive参数,防止防火墙断开长连接
4. 安全注意事项
4.1 认证与授权
启用认证:
yaml
security:
authorization: enabled
keyFile: /opt/mongodb/keyfile # 副本集内部认证
创建管理员用户:
javascript
use admin
db.createUser({
user: "admin",
pwd: "securePassword",
roles: [{ role: "root", db: "admin" }]
})
4.2 内部认证
- KeyFile机制:副本集成员使用相同的KeyFile进行内部认证
- 生成KeyFile :
openssl rand -base64 756 > /opt/mongodb/keyfile - 权限设置 :
chmod 400 /opt/mongodb/keyfile
4.3 网络隔离
- 绑定IP :
bindIp配置为内网IP,避免暴露到公网 - 防火墙规则:仅允许信任IP访问MongoDB端口
- VPN/专线:跨数据中心部署时使用安全隧道
4.4 TLS/SSL加密
yaml
net:
tls:
mode: requireTLS
certificateKeyFile: /etc/ssl/mongodb.pem
CAFile: /etc/ssl/ca.pem
allowConnectionsWithoutCertificates: false
4.5 安全最佳实践
| 类别 | 最佳实践 |
|---|---|
| 最小权限 | 使用角色授权,遵循最小权限原则 |
| 审计日志 | 启用审计功能,记录关键操作 |
| 定期更新 | 保持MongoDB版本最新,及时修复安全漏洞 |
| 备份加密 | 备份文件加密存储 |
| 传输加密 | 启用TLS加密所有数据传输 |
5. 建立副本集(二)
5.1 向现有副本集添加节点
添加新数据节点:
javascript
// 添加普通从节点
rs.add("host4:27017")
// 添加仲裁节点
rs.addArb("host4:27017")
// 指定优先级添加
rs.add({ host: "host4:27017", priority: 1, votes: 1 })
5.2 初始化数据同步
新节点加入后的数据同步方式:
| 同步方式 | 适用场景 | 特点 |
|---|---|---|
| 初始同步 | 新节点首次加入 | 从其他节点全量拷贝数据,自动完成 |
| 增量同步 | 节点重启后 | 从oplog拉取缺失操作,快速追赶上 |
| 手动同步 | 数据量极大时 | 使用mongodump/mongorestore或文件快照方式 |
初始同步过程:
- 节点进入STARTUP2状态
- 选择同步源(默认从主节点或最近节点)
- 克隆所有数据库文件
- 应用同步期间的oplog
- 转换为SECONDARY状态
5.3 配置优先级和选举权重
javascript
// 调整节点配置
var cfg = rs.conf()
cfg.members[0].priority = 2 // 优先级越高,越可能成为主节点
cfg.members[1].priority = 1
cfg.members[2].priority = 0 // 优先级0节点永远不能成为主节点
rs.reconfig(cfg)
5.4 添加延迟节点
javascript
// 添加延迟1小时的从节点(用于误操作恢复)
rs.add({
host: "host4:27017",
priority: 0,
hidden: true, // 隐藏节点,不接收读请求
slaveDelay: 3600 // 延迟秒数
})
6. 观察副本集
6.1 常用管理命令
| 命令 | 功能 | 示例 |
|---|---|---|
rs.status() |
查看副本集详细状态 | 成员健康度、角色、optime |
rs.conf() |
查看副本集配置 | 成员列表、优先级、心跳配置 |
rs.isMaster() |
查看主节点信息 | 当前主节点、是否为主节点 |
db.isMaster() |
同 rs.isMaster() | 快速判断节点角色 |
db.printReplicationInfo() |
查看oplog信息 | 大小、时间范围 |
db.printSlaveReplicationInfo() |
查看从节点同步延迟 | 各从节点的同步状态 |
6.2 关键指标解读
从 rs.status() 输出的关键字段:
stateStr:节点状态(PRIMARY/SECONDARY/RECOVERING等)health:健康状态(1健康,0异常)optime:当前节点的最新操作时间戳optimeDate:optime对应的可读时间syncingTo:从节点正在从哪个节点同步lastHeartbeat:上次心跳时间lastHeartbeatRecv:上次收到心跳时间
6.3 监控与告警
需要监控的核心指标:
- 节点可用性:各节点健康状态
- 复制延迟:从节点滞后主节点的时间
- Oplog窗口:oplog可保留的时间范围,低于24小时需告警
- 选举次数:异常选举可能表示网络问题或节点不稳定
- 主节点切换频率:频繁切换影响业务
7. 更改副本集配置
7.1 重新配置副本集
javascript
// 1. 获取当前配置
var cfg = rs.conf()
// 2. 修改配置(例如:修改心跳超时时间)
cfg.settings = {
heartbeatTimeoutSecs: 15, // 心跳超时,默认10秒
electionTimeoutMillis: 15000 // 选举超时,默认10秒
}
// 3. 应用配置(force参数用于处理无法达到多数的情况)
rs.reconfig(cfg)
// 或强制重新配置(慎用)
rs.reconfig(cfg, { force: true })
7.2 常见配置修改场景
| 修改场景 | 操作示例 | 注意事项 |
|---|---|---|
| 删除节点 | rs.remove("host1:27017") |
确保删除后剩余节点满足多数选举 |
| 修改优先级 | cfg.members[0].priority = 3 |
优先级0节点不能成为主节点 |
| 调整为隐藏节点 | cfg.members[1].hidden = true |
隐藏节点不接受读请求 |
| 设置延迟节点 | cfg.members[2].slaveDelay = 7200 |
延迟节点需设置priority=0 |
| 调整投票数 | cfg.members[0].votes = 1 |
投票数可为0或1 |
| 修改oplog大小 | 需重新配置或使用 replSetResizeOplog |
修改后需要重新同步 |
7.3 动态调整oplog大小
javascript
// MongoDB 3.6+ 支持动态调整
db.adminCommand({
replSetResizeOplog: 1,
size: 10240 // 单位:MB,这里设置为10GB
})
7.4 维护模式
javascript
// 将节点设置为维护模式(接收不到读请求)
db.adminCommand({ replSetMaintenance: true })
// 退出维护模式
db.adminCommand({ replSetMaintenance: false })
8. 如何设计副本集
8.1 副本集设计原则
| 设计原则 | 说明 |
|---|---|
| 奇数节点 | 保证选举时能获得多数票,避免平局 |
| 跨故障域部署 | 节点分布在不同机架、可用区或数据中心 |
| 至少3个数据节点 | 2个数据节点+仲裁者也能工作,但推荐3个数据节点 |
| 考虑网络分区 | 避免将多数节点集中在同一网络段 |
| 合理的优先级 | 将性能更好的节点设置更高优先级 |
8.2 常见部署架构
单数据中心部署:
[Primary] --- [Secondary1]
| |
+----[Secondary2]
- 优势:低延迟,管理简单
- 风险:数据中心故障导致服务不可用
双数据中心部署:
数据中心A 数据中心B
[Primary] [Secondary2]
[Secondary1] [Arbiter] (可选)
- 优势:提高可用性
- 风险:网络分区可能导致选举问题
三数据中心部署(推荐):
数据中心A 数据中心B 数据中心C
[Primary] [Secondary1] [Secondary2]
- 优势:任意一个数据中心故障,仍保留多数节点
- 最佳实践:至少3个数据节点分布在3个数据中心
8.3 跨地域部署考虑
- 写关注 :使用
{ w: "majority" }确保数据跨地域持久化 - 读偏好 :设置
readPreference: nearest读取最近节点,降低延迟 - 网络延迟:跨地域部署会增加写入延迟,需权衡一致性要求
- 标签集:使用标签控制读写路由策略
8.4 容量规划
| 资源 | 规划建议 |
|---|---|
| 磁盘 | 数据量 × 3(数据+oplog+索引)+ 预留空间 |
| 内存 | 热数据集大小 + 索引大小 + 操作系统开销 |
| CPU | 根据并发量和写入负载评估,建议4核以上 |
| 网络 | 千兆以上网络,考虑复制流量 |
9. 成员配置选项
9.1 成员配置参数详解
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
_id |
整数 | 无 | 成员唯一标识,从0开始递增 |
host |
字符串 | 无 | 主机名和端口 |
priority |
浮点数 | 1 | 选举优先级,0-1000,0不能成为主节点 |
votes |
整数 | 1 | 投票权,0或1,最多7个有投票权的节点 |
hidden |
布尔值 | false | 隐藏节点,不响应读请求 |
slaveDelay |
整数 | 0 | 延迟同步秒数,需配合priority=0 |
arbiterOnly |
布尔值 | false | 是否为仲裁节点 |
buildIndexes |
布尔值 | true | 是否创建索引,设置为false需配合priority=0 |
tags |
对象 | {} | 标签,用于读写策略控制 |
9.2 节点类型及配置
| 节点类型 | 配置示例 | 用途 |
|---|---|---|
| 标准节点 | { priority: 1, votes: 1 } |
默认配置,可成为主节点并参与投票 |
| 高优先级节点 | { priority: 2, votes: 1 } |
更倾向于成为主节点,适合性能更好的机器 |
| 被动节点 | { priority: 0, votes: 1 } |
不成为主节点,但参与投票,适合备份节点 |
| 隐藏节点 | { priority: 0, hidden: true } |
不接收读请求,适合数据分析或备份 |
| 延迟节点 | { priority: 0, slaveDelay: 3600, hidden: true } |
保留历史数据,用于误操作恢复 |
| 仲裁节点 | { arbiterOnly: true } |
仅投票,不存储数据,节省资源 |
| 无索引节点 | { buildIndexes: false, priority: 0 } |
不创建索引,适用于只做备份的节点 |
9.3 标签集配置
配置标签:
javascript
var cfg = rs.conf()
cfg.members[0].tags = { "dc": "beijing", "rack": "A", "use": "prod" }
cfg.members[1].tags = { "dc": "beijing", "rack": "B", "use": "prod" }
cfg.members[2].tags = { "dc": "shanghai", "rack": "C", "use": "backup" }
rs.reconfig(cfg)
使用标签设置读偏好:
javascript
// 只读取北京机房的节点
db.collection.find().readPref("primaryPreferred", [
{ "dc": "beijing" }
])
使用标签设置写关注:
javascript
// 写入至少两个不同机房的节点
db.collection.insert(
{ data: "value" },
{ writeConcern: { w: "majority", wtimeout: 5000 } }
)
9.4 成员配置最佳实践
- 仲裁节点:部署在独立服务器,避免与数据节点共用
- 隐藏节点:用于备份和分析任务,减少对主节点压力
- 延迟节点:设置延迟时间为业务误操作可恢复的时间窗口(如8-24小时)
- 优先级设置:将性能更好、网络更稳定的节点设置更高优先级
- 标签策略:为节点打标签,实现精细化的读写路由控制
通过以上知识点的系统梳理,可以全面掌握MongoDB副本集的创建、配置、管理和优化方法,为构建高可用、高可靠的MongoDB生产环境奠定坚实基础。