外观
MongoDB 自动故障转移
故障检测机制
心跳检测
心跳过程:
- 每个节点定期向其他节点发送心跳包
- 默认每 2 秒发送一次
- 心跳包包含节点状态、复制延迟等信息
- 节点通过心跳检测其他节点的可用性
故障判断条件:
- 连续多次未收到心跳响应
- 默认超时时间为 10 秒(5 个心跳间隔)
- 可以通过配置参数调整
- 当多数节点认为主节点不可用时,触发选举
网络分区处理
脑裂问题:
- 网络分区导致副本集分裂成多个子集群
- 每个子集群可能尝试选举自己的主节点
- 可能导致数据不一致
解决方案:
- 使用多数票机制,只有获得多数票的节点才能成为主节点
- 确保网络分区后只有一个子集群能获得多数票
- 避免使用偶数个节点,防止无法形成多数票
选举机制
选举触发条件
主要触发条件:
- 主节点故障或网络中断
- 副本集初始化
- 主节点主动降级(step down)
- 副本集配置变更
- 选举超时
选举过程:
- 从节点检测到主节点不可用
- 从节点将自己的状态改为 "候选节点"(Candidate)
- 候选节点向所有投票节点发送选举请求
- 投票节点根据选举规则进行投票
- 候选节点统计收到的票数
- 获得多数票的候选节点成为新主节点
- 新主节点通知所有节点,更新自身状态
选举规则
投票节点资格:
- 必须是健康的节点
- 必须能够与多数节点通信
- 必须具有投票权(votes: 1)
- 必须是数据节点(不是仲裁节点)
候选人资格:
- 必须是从节点
- 必须具有最新的 oplog
- 必须能够与多数节点通信
- 优先级(priority)越高,越有可能被选为新主节点
投票规则:
- 每个投票节点只能投一票
- 节点只能投票给比自己数据更新的候选人
- 节点不能投票给自己(除非没有其他候选人)
- 获得多数票的候选人成为新主节点
故障转移配置
配置参数
心跳相关参数:
yaml
replication:
replSetName: rs0
heartbeatIntervalMillis: 2000 # 心跳间隔,默认 2000 毫秒
electionTimeoutMillis: 10000 # 选举超时时间,默认 10000 毫秒
catchUpTimeoutMillis: 2000 # 数据追赶超时时间,默认 2000 毫秒优先级配置:
yaml
replication:
replSetName: rs0
members:
- host: "localhost:27017"
priority: 2 # 主节点优先级
- host: "localhost:27018"
priority: 1 # 从节点优先级
- host: "localhost:27019"
priority: 1 # 从节点优先级
- host: "localhost:27020"
arbiterOnly: true # 仲裁节点运行时调整
调整心跳间隔:
javascript
db.adminCommand({
setParameter: 1,
heartbeatIntervalMillis: 1000 // 将心跳间隔调整为 1 秒
})调整选举超时时间:
javascript
db.adminCommand({
setParameter: 1,
electionTimeoutMillis: 5000 // 将选举超时时间调整为 5 秒
})手动触发故障转移:
javascript
// 主节点主动降级
rs.stepDown()
// 强制重新配置副本集
rs.reconfig(cfg, { force: true })故障转移监控
状态查看
查看副本集状态:
javascript
rs.status()查看当前主节点:
javascript
rs.status().members.find(m => m.stateStr === "PRIMARY").name查看节点状态码:
- 0: STARTUP - 正在启动
- 1: PRIMARY - 主节点
- 2: SECONDARY - 从节点
- 3: RECOVERING - 恢复中
- 5: STARTUP2 - 正在同步数据
- 6: ARBITER - 仲裁节点
- 7: DOWN - 不可用
- 8: ROLLBACK - 回滚中
- 9: UNKNOWN - 未知状态
日志监控
选举日志:
2023-01-01T12:00:00.000+0000 I REPL [replexec-0] Scheduled new election in 0ms to choose new PRIMARY.
2023-01-01T12:00:00.000+0000 I REPL [replexec-0] conducting a dry run election to see if we could be elected
2023-01-01T12:00:00.000+0000 I REPL [replexec-0] dry election run succeeded, running for election
2023-01-01T12:00:00.000+0000 I REPL [replexec-0] election succeeded, assuming primary role in term 2
2023-01-01T12:00:00.000+0000 I REPL [replexec-0] transition to PRIMARY from SECONDARY故障检测日志:
2023-01-01T12:00:00.000+0000 I REPL [heartbeatReceiver] Heartbeat failed for member primary:27017; Location18918: Our replica set configuration is invalid or does not include us
2023-01-01T12:00:00.000+0000 I REPL [ReplicationExecutor] Member primary:27017 is now in state DOWN
2023-01-01T12:00:00.000+0000 I REPL [ReplicationExecutor] Starting an election, since we've seen no PRIMARY in the past 10000ms性能监控
监控指标:
- 选举次数和频率
- 故障转移时间
- 复制延迟
- 心跳成功率
- 节点状态变化
监控工具:
- MongoDB Atlas 监控面板
- mongostat 和 mongotop
- 第三方监控工具(如 Prometheus + Grafana)
- 日志分析工具
故障转移最佳实践
副本集配置
节点数量:
- 建议使用奇数个节点(3、5 或 7 个)
- 避免使用偶数个节点,防止无法形成多数票
- 考虑业务的可用性要求和成本
节点分布:
- 跨可用区部署,提高容灾能力
- 避免所有节点部署在同一物理位置
- 考虑网络延迟,确保节点间通信顺畅
优先级配置:
- 为重要节点设置较高的优先级
- 为延迟节点设置较低的优先级
- 避免频繁的主节点切换
性能优化
网络优化:
- 确保节点间网络带宽充足
- 减少节点间的网络延迟
- 避免网络拥塞
资源配置:
- 为主节点分配足够的 CPU 和内存
- 使用 SSD 存储,提高数据同步速度
- 确保足够的磁盘空间
配置优化:
- 根据实际情况调整心跳间隔和选举超时时间
- 优化复制配置,减少复制延迟
- 确保所有节点的配置一致
故障转移测试
定期测试:
- 定期模拟主节点故障,测试自动故障转移
- 记录故障转移时间和过程
- 验证故障转移后的系统状态
- 测试客户端重新连接
测试方法:
- 关闭主节点进程
- 断开主节点网络连接
- 使用
rs.stepDown()命令手动触发 - 模拟网络分区
测试注意事项:
- 在业务低峰期进行测试
- 提前通知相关团队
- 准备回滚方案
- 记录测试结果和经验教训
常见问题(FAQ)
Q1: 如何查看副本集的当前状态?
A1: 可以使用 rs.status() 命令查看副本集的当前状态,包括节点状态、主节点信息、复制延迟等。
Q2: 故障转移需要多长时间?
A2: 故障转移通常需要 10-30 秒,具体取决于:
- 副本集配置(心跳间隔、选举超时时间)
- 网络状况
- 节点数量和分布
- 复制延迟
Q3: 如何减少故障转移时间?
A3: 可以通过以下方式优化:
- 减小心跳间隔(heartbeatIntervalMillis)
- 减小选举超时时间(electionTimeoutMillis)
- 确保低复制延迟
- 优化网络连接
- 合理配置节点优先级
Q4: 什么是脑裂问题?如何避免?
A4: 脑裂问题是指网络分区导致副本集分裂成多个子集群,每个子集群可能尝试选举自己的主节点。避免方法:
- 使用奇数个节点,确保网络分区后只有一个子集群能获得多数票
- 跨可用区部署,减少网络分区的影响
- 合理配置节点优先级
Q5: 如何手动触发故障转移?
A5: 可以使用 rs.stepDown() 命令让主节点主动降级,触发新的选举。
Q6: 仲裁节点在故障转移中起什么作用?
A6: 仲裁节点不存储数据,只参与选举投票,帮助副本集在偶数节点情况下达成多数票,提高选举成功率。
Q7: 如何确保故障转移后数据一致性?
A7: MongoDB 使用 oplog 保证数据的最终一致性,故障转移过程中:
- 只有数据最新的节点才能被选为新主节点
- 新主节点会继续从旧主节点的 oplog 同步数据
- 可以使用 write concern 确保数据写入多数节点
Q8: 故障转移对客户端有什么影响?
A8: 故障转移期间:
- 可能出现短暂的服务不可用(10-30 秒)
- 客户端需要重新连接到新主节点
- 建议客户端使用副本集连接字符串,自动发现新主节点
- 可以配置合适的连接超时和重试机制
