面试题答案
一键面试诊断问题步骤
- 检查分片节点状态:
- 使用
sh.status()
命令查看分片集群的整体状态,确认故障分片节点的具体信息,如节点名称、IP 等。 - 查看 MongoDB 日志文件,在日志文件中查找与故障分片节点相关的错误信息,例如网络连接问题、磁盘故障相关提示等。
- 使用
- 分析索引损坏情况:
- 针对每个集合,使用
db.collection.validate()
命令,该命令会检查集合的完整性,包括索引状态。它会返回索引是否存在损坏以及损坏的详细信息,如缺失的索引键等。 - 查看查询性能下降相关的慢查询日志,分析哪些查询受到索引损坏的影响最大,确定涉及的集合和索引。
- 针对每个集合,使用
修复和优化方案
- 处理故障分片节点:
- 故障排查与修复:
- 如果是硬件问题(如磁盘故障、网络故障),更换或修复相应硬件。例如磁盘故障,更换新磁盘后重新挂载并配置权限。
- 如果是软件问题(如 MongoDB 服务崩溃),检查 MongoDB 服务日志确定崩溃原因,如内存不足导致服务崩溃,可调整系统资源分配或优化 MongoDB 配置参数(如
wiredTigerCacheSizeGB
)后重启服务。
- 数据同步:
- 当故障节点修复后,让其重新加入分片集群。使用
rs.add()
命令将节点重新添加到副本集(如果是副本集分片节点)。 - 等待数据同步完成,可通过查看副本集状态(
rs.status()
)来监控同步进度,重点关注syncingTo
字段和optimeDate
等信息,确保数据与其他节点一致。
- 当故障节点修复后,让其重新加入分片集群。使用
- 故障排查与修复:
- 修复损坏索引:
- 重建索引:
- 对于确定损坏的索引,在维护窗口内对受影响的集合重建索引。使用
db.collection.dropIndex()
先删除损坏的索引,然后使用db.collection.createIndex()
重新创建索引。例如db.users.dropIndex({name: 1}); db.users.createIndex({name: 1})
。 - 在重建索引过程中,为减少对业务的影响,可采用在线重建索引的方式(如果 MongoDB 版本支持)。例如在 MongoDB 4.2 及以上版本,创建索引时可使用
{background: true}
选项,让索引在后台创建,减少对前台业务操作的阻塞。
- 对于确定损坏的索引,在维护窗口内对受影响的集合重建索引。使用
- 数据校验与修复:
- 在重建索引后,再次使用
db.collection.validate()
命令校验索引的完整性,确保索引已正确修复。 - 如果在索引重建过程中发现数据存在不一致情况,可使用
mongodump
和mongorestore
工具对集合进行数据修复。先对受影响集合进行备份mongodump -d yourDatabase -c yourCollection -o backupDir
,然后删除集合db.yourCollection.drop()
,再使用备份数据恢复mongorestore -d yourDatabase -c yourCollection backupDir/yourDatabase/yourCollection.bson
。
- 在重建索引后,再次使用
- 重建索引:
- 确保高可用性和数据一致性:
- 副本集配置优化:
- 确保每个分片的副本集有足够的成员,一般建议至少 3 个成员(1 个主节点,2 个从节点),以提高可用性和数据冗余。
- 合理配置副本集的选举优先级,将性能较好、稳定性高的节点设置为较高优先级,避免频繁的主节点切换。例如,在副本集配置文件中设置
{ "_id": 0, "host": "node1:27017", "priority": 2 }
。
- 监控与预警:
- 部署监控工具(如 Prometheus + Grafana),实时监控分片集群的各项指标,包括节点状态、索引使用情况、查询性能等。设置阈值,当指标异常时及时发出预警,例如当某个分片节点的磁盘使用率超过 80% 时发出警报。
- 定期进行数据一致性检查,例如使用
db.runCommand({replSetGetStatus: 1})
命令检查副本集成员之间的数据一致性,确保数据在各个节点上保持同步。
- 副本集配置优化:
- 减少对业务影响:
- 维护窗口安排:选择业务低峰期进行上述修复和优化操作,如凌晨 2 - 6 点,此时对业务的影响最小。
- 读写分离:在修复过程中,将读操作尽量分配到其他正常的分片节点或副本集从节点,通过配置连接字符串或使用中间件(如 MongoDB Sharding Proxy)实现读写分离,减少对主节点的压力,从而降低对业务的影响。例如在应用程序连接字符串中设置
readPreference=secondaryPreferred
。