美图后端开发一面面经

美图 · 后端开发工程师 · 一面 · 2026-05

《面试题目》

八股

  1. Java HashMap 的 put 流程
  2. synchronized 与自旋锁的区别
  3. 一个线程等待多个线程完成,用什么来实现?
  4. 数据库为什么索引能提高检索速度
  5. 联合索引失效场景,为什么失效
  6. Redis 缓存击穿、穿透、雪崩问题,如何解决

项目1(Agent对话)

  1. Agent 对话链路的设计
  2. 结构化记忆和长期记忆的内容上的区别
  3. 模型幻觉或健康风险的规避措施
  4. 数据来源,如何入库和召回
  5. 评测数据集怎么构造的,答案打分怎么设计

项目2(图片上传)

  1. 图片上传流程
  2. 如何保证上传链路中的文件完整性,确保用户上传的图片和 OSS 中最终存储的图片内容一致?
  3. 如何保证其他用户无法通过破解接口获取别人空间的数据?如何避免越权访问?
  4. 双重缓存,如何保证数据一致性?

《参考解析》

  1. HashMap put 流程:先对 key 计算 hashCode 并做扰动处理,再与 (容量-1) 按位与得到桶下标;若该桶为空则直接放入新节点;若已有节点则比较 key 是否相同(hashCode相同且equals相同)决定覆盖 value 还是插入链表/红黑树;插入后检查链表长度是否达到树化阈值(8)及数组容量是否达到 64,最后判断元素总数是否超过扩容阈值(容量×负载因子),超过则触发扩容。
  2. synchronized vs 自旋锁:自旋锁是一种锁的实现思路——线程获取锁失败时不立即阻塞挂起,而是循环(自旋)不断重试,避免线程切换的开销,适合锁持有时间很短的场景;synchronized 在 JDK6 之后引入了锁升级机制(偏向锁→轻量级锁→重量级锁),其中轻量级锁阶段本质上就采用了自旋+CAS的方式尝试获取锁,只有自旋一定次数仍失败才会膨胀为重量级锁(真正调用操作系统级别的互斥量,线程被挂起)。
  3. 文件完整性校验:上传时对文件内容计算哈希值(如 MD5/SHA256)并随请求一起提交,服务端接收后重新计算文件哈希并与客户端提交的值比对,或者利用 OSS 提供的 Content-MD5 请求头校验机制,由对象存储服务在写入时自动校验完整性,避免网络传输过程中数据损坏或被篡改。
  4. 越权访问防护:核心是”鉴权到资源维度”而非仅”鉴权到接口维度”——每次访问具体资源(如某张图片、某个空间)时,都要校验当前登录用户是否对该资源 ID 拥有权限(而不能仅凭接口本身的登录态校验就放行),常见做法是在资源归属字段(ownerId)与当前登录用户做比对,或引入统一的权限中间件按资源类型+操作类型做集中校验。