面试题答案
一键面试1. 索引管理
- 复合索引:为了支持不同的排序需求,创建多个复合索引。例如,创建
{user_id: 1, likes: -1, post_time: -1}
索引,用于按照点赞数和发布时间排序;创建{user_id: 1, comments: -1, post_time: -1}
索引,用于按照评论数和发布时间排序。这里user_id
放在首位,是为了支持按用户维度的查询,提高查询效率。-1
表示降序排序。 - 部分索引:如果某些用户偏好的查询模式相对固定,可以考虑创建部分索引。例如,对于经常按照点赞数排序查看动态的用户群体,可以创建只包含这部分用户的
{user_id: 1, likes: -1, post_time: -1}
部分索引,减少索引占用空间和维护成本。
2. 查询优化
- 利用索引:在查询时,确保查询语句能够正确使用到上述创建的索引。例如,对于按照点赞数和发布时间排序的查询
db.posts.find({user_id: userId}).sort({likes: -1, post_time: -1})
,确保sort
字段顺序与索引字段顺序一致,这样 MongoDB 可以高效地利用索引进行排序操作。 - 投影优化:只返回需要的字段,减少网络传输和处理的数据量。例如
db.posts.find({user_id: userId}, {user_id: 1, likes: 1, post_time: 1, content: 1, _id: 0}).sort({likes: -1, post_time: -1})
,这里_id
默认会返回,设置为0
不返回,减少数据量。
3. 分布式技术
- 分片:可以采用基于
user_id
的范围分片策略。将不同user_id
范围的数据分布到不同的分片服务器上,这样可以将高并发请求分散到多个节点处理,提高整体的并发处理能力。例如,按照user_id
的哈希值进行分片,确保数据均匀分布。 - 副本集:搭建副本集,主节点负责处理写操作,从节点负责处理读操作。这样可以将读请求分摊到多个从节点上,减轻主节点压力,提高系统的读性能。同时,副本集还提供了数据冗余和高可用性,当主节点出现故障时,从节点可以自动选举成为新的主节点,保证系统的正常运行。
4. 应对热点数据的策略
- 缓存:使用 Redis 等缓存工具,对于热门用户的动态数据进行缓存。当用户请求查看动态列表时,先从缓存中获取数据,如果缓存中没有,则查询 MongoDB 并将结果写入缓存。这样可以大大减轻数据库的压力,提高响应速度。例如,对于点赞数或评论数特别高的用户动态,可以设置较长的缓存时间。
- 限流:对每个用户的请求频率进行限制,防止某个用户短时间内发起大量请求导致系统资源耗尽。可以使用令牌桶算法或漏桶算法实现限流,例如,设定每个用户每秒最多只能发起 10 次查看动态列表的请求。
- 数据预热:对于一些热点数据,提前将其加载到缓存中,避免在高并发情况下缓存击穿的问题。例如,在系统启动时,将热门用户的最新动态数据预先加载到 Redis 缓存中。