面试题答案
一键面试添加成员策略
- 评估资源:在添加成员前,评估新成员服务器的硬件资源(CPU、内存、存储、网络带宽),确保其能够承载新的负载。检查网络连接稳定性,新成员与现有副本集成员之间网络延迟应尽量低,一般建议控制在毫秒级。
- 选择添加顺序:先添加优先级较低的成员(如优先级为0的仲裁节点或延迟副本),这些成员对数据同步和选举影响较小。然后根据业务需求添加普通数据承载成员。添加数据承载成员时,按照网络拓扑的邻近性依次添加,例如先添加同一数据中心内的成员,再添加跨数据中心的成员。
- 数据同步:添加成员后,MongoDB会自动进行数据同步。为避免对现有业务读写造成过大影响,可以在业务低峰期进行添加操作。监控同步进度,通过
rs.status()
命令查看新成员的stateStr
字段,如“STARTUP2”表示正在同步数据,“PRIMARY”或“SECONDARY”表示同步完成。同时关注syncingTo
字段,确认同步源。 - 网络拓扑考量:如果是跨数据中心添加成员,要考虑数据中心之间的网络带宽和延迟。可以设置合适的心跳频率和选举超时时间,以适应不同网络状况。例如,对于网络延迟较高的跨数据中心链路,适当增加心跳频率(通过
replSetHeartbeatIntervalSecs
参数),同时增大选举超时时间(electionTimeoutMillis
参数),避免因网络波动导致不必要的选举。
移除成员策略
- 确认移除成员状态:使用
rs.status()
命令查看要移除成员的状态,确保其不是 PRIMARY 节点。如果是 PRIMARY,需要先进行手动故障转移,将 PRIMARY 角色转移到其他健康的 SECONDARY 节点,使用rs.stepDown()
命令。 - 停止写入:为防止在移除过程中数据不一致,在移除成员所在服务器上停止所有写操作,可通过应用层逻辑或者在 MongoDB 层面设置写锁(如使用
db.fsyncLock()
,操作完成后使用db.fsyncUnlock()
解锁,但此方法会阻塞所有读写操作,需谨慎使用)。 - 移除顺序:先移除数据承载成员,移除后监控副本集状态,确保剩余成员数据同步正常且副本集整体功能不受影响。最后移除仲裁节点等特殊成员。移除成员使用
rs.remove("<memberHost:port>")
命令。 - 数据清理:移除成员后,在原服务器上清理 MongoDB 数据文件,避免数据残留占用空间。同时检查日志文件,确保移除过程无异常记录。
避免数据丢失或不一致
- 写关注(Write Concern):在应用层写入操作时,使用合适的写关注级别。如对于关键业务数据,使用
w: "majority"
确保数据写入大多数副本集成员后才返回成功,这能保证数据在多数节点持久化,降低数据丢失风险。 - 复制因子与容错性:确保副本集有足够的复制因子(一般建议至少3个成员),以提供容错能力。当某个成员故障或被移除时,其他成员能继续提供服务且数据不会丢失。
- 心跳检测与自动恢复:MongoDB 通过心跳机制检测成员状态。确保心跳配置合理,及时发现成员故障并进行自动故障转移。同时,定期检查副本集配置,确保
members[n].priority
、members[n].votes
等参数设置正确,避免因配置问题导致选举异常从而引发数据不一致。
监控与调整副本集状态
- 监控工具:使用 MongoDB 自带的监控命令如
rs.status()
、db.serverStatus()
获取副本集和服务器的状态信息,包括成员状态、同步进度、内存使用、网络连接等。结合第三方监控工具如 Prometheus + Grafana,实时监控副本集的各项指标,如写入吞吐量、读取延迟、复制滞后等。设置告警规则,当指标超出阈值(如复制滞后时间超过10秒)时及时通知运维人员。 - 动态调整:根据监控数据动态调整副本集。如发现某个成员负载过高,可以考虑将其优先级降低或者移除并添加新的成员分担负载。如果业务读请求量增加,可以添加更多的 SECONDARY 节点用于读负载均衡。同时,根据网络状况调整心跳频率和选举超时时间等参数,确保副本集在不同网络环境下都能稳定运行。