外观
MongoDB 副本集角色
主节点(Primary)
主节点功能
写操作处理:
- 接收并处理所有客户端写请求
- 将写操作记录到 oplog(操作日志)
- 确保写操作的原子性和持久性
- 向客户端返回写操作结果
数据同步管理:
- 维护与所有从节点的连接
- 向从节点发送 oplog 记录
- 监控从节点的同步状态
- 处理从节点的同步请求
选举参与:
- 在初始选举中参与竞选
- 当自身不可用时触发重新选举
- 支持强制重新配置
主节点选举
选举触发条件:
- 副本集初始化
- 主节点故障或网络中断
- 主节点主动降级
- 副本集配置变更
选举过程:
- 从节点检测到主节点不可用
- 从节点发起选举请求
- 所有投票节点进行投票
- 获得多数票的节点成为新主节点
- 新主节点通知所有节点
选举条件:
- 节点必须是健康的
- 节点必须具有最新的 oplog
- 节点必须能够与大多数节点通信
- 节点必须具有选举权
从节点(Secondary)
从节点功能
数据复制:
- 从主节点复制 oplog
- 应用 oplog 到本地数据库
- 维护与主节点的数据一致性
- 支持不同的复制延迟设置
读操作支持:
- 默认情况下不处理读请求
- 可以配置为接收读请求
- 支持多种读偏好设置
- 提供数据冗余和高可用性
选举参与:
- 参与选举投票
- 可以被选举为新主节点
- 监控主节点状态
从节点配置
读偏好设置:
javascript
// 连接字符串配置
mongodb://localhost:27017,localhost:27018,localhost:27019/?readPreference=secondary
// 客户端代码配置
db = db.getSiblingDB('test');
db.collection('users').find().readPref('secondary');复制延迟配置:
javascript
// 设置延迟节点
cfg = rs.conf();
cfg.members[2].secondaryDelaySecs = 3600; // 延迟1小时
cfg.members[2].hidden = true;
rs.reconfig(cfg);隐藏节点配置:
javascript
// 设置隐藏节点
cfg = rs.conf();
cfg.members[2].hidden = true;
rs.reconfig(cfg);仲裁节点(Arbiter)
仲裁节点功能
选举投票:
- 参与选举投票,但不参与竞选
- 帮助副本集在偶数节点情况下达成多数票
- 不存储任何数据,仅维护副本集配置
状态监控:
- 监控主节点状态
- 向其他节点发送心跳
- 参与副本集状态维护
仲裁节点部署
部署场景:
- 副本集节点数为偶数时
- 需要降低硬件成本时
- 跨数据中心部署时
部署方式:
bash
# 启动仲裁节点
docker run -d \
--name mongodb-arbiter \
-p 27020:27017 \
mongo:6.0 --replSet rs0 --smallfiles
# 添加仲裁节点到副本集
rs.addArb("localhost:27020")注意事项:
- 仲裁节点不应与主节点部署在同一台服务器上
- 仲裁节点不应与其他仲裁节点部署在同一台服务器上
- 仲裁节点不需要大量的资源
特殊角色配置
延迟节点(Delayed)
延迟节点用途:
- 用于恢复误删除或误修改的数据
- 提供时间窗口进行数据恢复
- 用于测试和验证
配置方法:
javascript
cfg = rs.conf();
cfg.members[2].secondaryDelaySecs = 7200; // 延迟2小时
cfg.members[2].hidden = true;
cfg.members[2].priority = 0; // 不参与竞选
rs.reconfig(cfg);使用场景:
- 恢复误删除的集合或数据库
- 恢复误修改的数据
- 测试灾难恢复流程
隐藏节点(Hidden)
隐藏节点用途:
- 用于备份和ETL操作
- 用于监控和分析
- 用于延迟节点
配置方法:
javascript
cfg = rs.conf();
cfg.members[2].hidden = true;
cfg.members[2].priority = 0;
rs.reconfig(cfg);特点:
- 对客户端不可见
- 不参与选举
- 仍参与数据复制
非投票节点
非投票节点用途:
- 增加副本集节点数超过7个时
- 用于只读副本
- 用于备份节点
配置方法:
javascript
cfg = rs.conf();
cfg.members[7].votes = 0; // 设置为非投票节点
rs.reconfig(cfg);注意事项:
- 副本集最多支持50个节点
- 最多支持7个投票节点
- 非投票节点不参与选举
角色管理命令
查看角色状态
查看副本集状态:
javascript
rs.status()查看节点配置:
javascript
rs.conf()查看节点角色:
javascript
// 连接到节点
use admin
// 查看当前节点角色
db.runCommand({ isMaster: 1 })修改角色配置
修改节点优先级:
javascript
cfg = rs.conf();
cfg.members[0].priority = 2; // 提高主节点优先级
cfg.members[1].priority = 1; // 设置从节点优先级
rs.reconfig(cfg);添加节点:
javascript
// 添加从节点
rs.add("localhost:27018")
// 添加带配置的节点
rs.add({
host: "localhost:27018",
priority: 1,
votes: 1
})
// 添加仲裁节点
rs.addArb("localhost:27020")移除节点:
javascript
// 移除节点
rs.remove("localhost:27018")
// 移除仲裁节点
rs.remove("localhost:27020")角色最佳实践
生产环境配置
节点数量:
- 建议使用奇数个节点(3、5或7个)
- 避免使用偶数个节点,除非添加仲裁节点
- 考虑业务的可用性要求
角色分配:
- 至少配置1个主节点和2个从节点
- 仅在必要时使用仲裁节点
- 配置适当的优先级,避免频繁选举
- 考虑跨数据中心部署
资源配置:
- 主节点需要更多的CPU和内存资源
- 从节点需要足够的磁盘空间
- 仲裁节点资源需求较低
性能优化
读操作分布:
- 使用读偏好将读操作分发到从节点
- 避免所有读操作集中在主节点
- 根据应用需求选择合适的读偏好
复制优化:
- 确保网络带宽足够支持复制
- 配置适当的复制延迟
- 监控复制延迟,及时处理延迟问题
选举优化:
- 配置适当的心跳间隔
- 设置合理的选举超时时间
- 避免频繁的配置变更
常见问题(FAQ)
Q1: 副本集最少需要多少个节点?
A1: 副本集最少需要1个节点,但生产环境建议至少3个节点(1个主节点,2个从节点)。单节点副本集不提供高可用性,仅用于测试。
Q2: 什么时候需要使用仲裁节点?
A2: 当副本集节点数为偶数时,需要添加仲裁节点以确保能够形成多数票。例如,2个节点的副本集需要1个仲裁节点,4个节点的副本集需要1个仲裁节点。
Q3: 主节点故障后,副本集会自动选举新主节点吗?
A3: 是的,当主节点故障或不可用时,副本集会自动触发选举,从可用的从节点中选举新主节点。选举过程通常在几秒钟内完成。
Q4: 如何防止某个节点被选举为主节点?
A4: 可以通过设置节点的优先级为0来防止其被选举为主节点:
javascript
cfg = rs.conf();
cfg.members[2].priority = 0;
rs.reconfig(cfg);Q5: 隐藏节点有什么用?
A5: 隐藏节点对客户端不可见,主要用于:
- 备份和ETL操作
- 监控和分析
- 延迟节点
- 测试环境
Q6: 如何查看当前主节点是谁?
A6: 可以通过以下命令查看当前主节点:
javascript
rs.status().members.find(m => m.stateStr === "PRIMARY").nameQ7: 副本集最多支持多少个节点?
A7: 副本集最多支持50个节点,但最多只有7个节点可以参与选举投票。超过7个节点的副本集需要将额外的节点配置为非投票节点。
Q8: 延迟节点的延迟时间应该设置为多少?
A8: 延迟时间取决于业务需求,建议设置为:
- 至少1小时,以便有足够的时间发现和恢复误操作
- 不超过24小时,避免延迟节点与主节点差距过大
- 根据数据变更频率和业务SLA调整
