面试题答案
一键面试性能优化
- 合理配置复制集
- 节点数量与分布:选择合适的复制集节点数量,一般推荐3到7个节点。奇数个节点有助于选举,避免脑裂问题。同时,将节点分布在不同的物理位置,减少因单一机房故障导致的服务中断。例如,在不同的云数据中心部署节点。
- 节点角色分配:明确主节点(Primary)、从节点(Secondary)和仲裁节点(Arbiter)的角色。主节点负责处理写操作,从节点复制主节点的数据并处理读操作,仲裁节点仅参与选举不存储数据。对于读多写少的场景,可以适当增加从节点数量来分担读压力。
- 优化文档结构
- 减少嵌套层次:复杂业务场景下文档可能较复杂,但应尽量减少嵌套层次。例如,如果有多层嵌套的数组或对象,考虑将其扁平化。以电商订单为例,若订单中商品详情有多层嵌套,可将商品详情提取为独立文档,通过引用关联,这样在查询和更新时能减少I/O操作。
- 预计算字段:对于一些需要频繁计算的字段,提前计算并存储。比如统计订单总金额,每次查询订单时计算总金额会增加计算开销,可在订单创建或商品信息更新时同步更新总金额字段。
- 索引优化
- 创建复合索引:根据业务查询需求创建复合索引。例如,若经常按照时间范围和用户ID查询文档,可创建包含时间字段和用户ID字段的复合索引,且要注意字段顺序对查询性能的影响,一般将选择性高的字段放在前面。
- 覆盖索引:设计查询时尽量使用覆盖索引,即查询所需的所有字段都包含在索引中。这样MongoDB无需回表查询文档,直接从索引中获取数据,大大提高查询效率。例如,若只查询文档的部分字段,确保这些字段都在索引中。
- 读写分离
- 读操作分发:利用从节点处理读请求,在应用程序层面配置读偏好(Read Preference)。如设置为
secondaryPreferred
,优先从从节点读取数据,在从节点不可用时从主节点读取。这能有效减轻主节点的读压力,提高系统整体性能。 - 写操作优化:批量写操作,将多个写操作合并为一个批量操作发送到主节点,减少网络开销。例如,使用
bulkWrite
方法代替多次单独的写操作。
- 读操作分发:利用从节点处理读请求,在应用程序层面配置读偏好(Read Preference)。如设置为
故障处理与事务完整性和数据一致性
- 故障检测与选举
- 心跳机制:MongoDB复制集节点间通过心跳机制互相监测状态,默认每2秒发送一次心跳包。当主节点出现故障时,从节点在一定时间(通常10秒左右)内未收到主节点心跳,会判定主节点故障。
- 选举过程:从节点发起选举,符合条件的从节点(如数据最新、优先级合适等)参与选举。仲裁节点在选举中起投票作用,它不存储数据,仅参与选举决策。通过Raft协议等机制,选出新的主节点,继续提供服务。
- 事务回滚与恢复
- 事务日志:在事务执行过程中,MongoDB会记录事务日志(Write-Ahead Log,WAL)。当某个节点出现故障时,新的主节点(或恢复后的节点)会根据事务日志进行恢复操作。对于未完成的事务,系统会进行回滚,确保数据一致性。例如,在一个涉及多个文档更新的事务中,若事务执行到一半节点故障,恢复时系统会根据日志撤销已完成但未提交的操作。
- 同步数据:故障节点恢复后,会从新的主节点同步数据,追赶上最新的状态。从节点通过
oplog
(操作日志)来同步主节点的写操作,保证数据最终一致性。在同步过程中,会确保事务相关的操作按顺序正确应用,以保证事务的完整性。