快手Java后端一面面经

快手 · Java后端开发工程师 · 一面 · 2026-06

《面试题目》

  1. 算法二选一:最长无重复字符子串 / 删除链表倒数第 k 个节点(选择了后者,中间卡顿但最终 AC)
  2. MVCC 解决了什么问题
  3. 既然已经有锁机制,为什么还需要 MVCC
  4. 一共有哪几种隔离级别,各自解决了什么问题
  5. RR(可重复读)级别解决了幻读吗
  6. 讲解一下什么是索引
  7. 讲解一下 B+树
  8. 索引失效的情况有哪些
  9. 如果对性别字段建立索引,查找的时候会走这个索引吗
  10. 性别字段走索引和全表扫描哪个更优
  11. 慢 SQL 优化手段
  12. RabbitMQ 的结构
  13. 消息有哪些路由模式
  14. 消息确认机制
  15. RabbitMQ 持久化策略
  16. Spring 怎么解决循环依赖
  17. 有哪些依赖注入的方式,以及有什么区别,推荐用哪一个

《参考解析》

  1. MVCC 与锁的关系:锁通过阻塞实现读写互斥,会牺牲并发性能;MVCC(多版本并发控制)通过为每行数据维护多个历史版本(配合 undo log 和 Read View),让读操作不加锁也能读到某个时间点的一致性快照,从而实现读写不冲突,大幅提升并发读的性能,二者是互补而非替代关系(写操作依然需要加锁)。
  2. RR 隔离级别与幻读:InnoDB 的可重复读级别通过 MVCC(快照读场景)+ 间隙锁/临键锁(当前读场景,如 select ... for update)共同作用,基本解决了幻读问题,但并非在所有场景下都能 100% 杜绝(例如快照读之后紧接当前读仍可能读到新插入的行)。
  3. 索引失效常见场景:对索引列做函数运算/隐式类型转换、使用 !=/<>like '%xx' 前置模糊匹配、or 连接非索引列、列的区分度过低(如性别字段只有男女两个值,全表扫描往往比走索引更快,因为回表成本更高)。
  4. Spring 循环依赖:通过三级缓存机制解决——一级缓存存完全初始化好的单例 Bean,二级缓存存提前暴露的半成品 Bean,三级缓存存 ObjectFactory 用于生成代理对象;Bean 实例化后立即暴露到三级缓存,属性注入阶段如果发现循环依赖,直接从三级缓存中取出(可能生成代理)放入二级缓存,从而打破循环。