钉钉 Java 暑期实习一面

面试题目

项目经验

  1. 请花大概五到十分钟,介绍一下你的项目经验,以及整体遇到的问题和如何解决的。
  2. 本地生活服务平台项目,是你一个人完成的还是团队合作完成的?
  3. 这个项目中,你觉得遇到了最重要、最难的问题是什么?你是如何解决的?
  4. 经过你这个缓存设计之后,整个系统 QPS 可以到多少?假如要扛 1 万 QPS,你觉得整个系统还需要做什么升级改造?
  5. 你怎么样去识别哪些数据是热点数据的?
  6. 假如系统一直运行得很好,突然某天出现了宕机,你觉得应该怎么去定位?大概的流程知道吗?
  7. 本地生活服务平台是在公司里面的经历,还是你们自己的学习项目?

秒杀与限流

  1. 你觉得秒杀系统和普通商品购买有什么不同?整个系统需要考虑什么因素?
  2. 如果系统现在能扛 1000 QPS,瞬间来了 3000-4000 个客户秒杀,可能会发生什么?应该有什么措施去缓解这种情况?
  3. 你滑动窗口限流用的是什么组件?大概是怎么实现的?
  4. 滑动窗口限流和固定窗口限流有什么区别?为什么用滑动窗口?

Redis 与 Lua

  1. 针对下单资格判断 Lua 脚本,脚本主要的逻辑是什么?
  2. 配合 Lua 脚本有没有什么注意事项?
  3. 假如因为 bug,这个 Lua 脚本执行需要 10 秒或 20 秒,你觉得系统可能会发生什么情况?
  4. 假设 Redis 的 Lua 脚本正在执行一个扣减操作还没执行完,其他客户端请求打过来了,它会阻塞吗?

本地缓存 Caffeine

  1. 你们的项目里面用到 Caffeine,为什么用它?主要用它做什么?架构设计上有什么考虑?
  2. Caffeine 的淘汰策略你大概知道吗?
  3. 如果 Redis 数据更新了,但 Caffeine 的数据还是旧的(双缓存不一致),什么情况下会出这种 bug?发生了要怎么办?

MySQL 与数据库

  1. 系统运行中如果出现慢 SQL,一般是什么原因?以及如何定位慢 SQL 问题?
  2. 假如系统用户量非常庞大(两三千万),要给数据库加索引的话,可能耗时两三个小时,在执行索引时需要注意什么?
  3. 即便做了缓存,MySQL 还是可能有瓶颈,这时候需要做哪些对 MySQL 的优化?
  4. 你说数据库做主从分离,读从库时,怎么样去保持主库和备库的数据一致性?

消息队列

  1. 对 Kafka 了解吗?它是怎么样保证消息顺序的?

系统监控与稳定性

  1. 你怎么样去测你的 QPS?你评估出来的 1000 QPS 主要是关注哪些指标?
  2. 你们整个系统有没有用到什么监控?你觉得应该做哪些监控去保证稳定?
  3. 假如系统突然之间 CPU 报警到 90%,或者内存马上要不足了,你应该怎么样去排查?
  4. 假如系统做了集群,其中有台机器持续报警,你没时间定位,最快的止血方式是什么?

订单与业务设计

  1. 订单系统里的超时关闭(延时任务),你觉得应该怎么实现?
  2. 怎么防范爬虫?
  3. 支付回调和关单任务可能同时操作同一个订单,应该怎么样去设计避免冲突?

Java 基础与并发

  1. 你大概知道什么是 CAS 吗?这里面可能会有什么问题?除了空耗 CPU 之外,还有什么其他问题?了解过 ABA 问题吗?
  2. 谈到锁的升级,可以大概说一下 Java(Synchronized)锁的升级策略吗?
  3. 如何避免死锁?如果系统中确实出现了死锁,要怎么样去排查?
  4. Java 的 equals 和 == 有什么区别?一般重写 equals 的话,为什么还需要重写 hashCode?

AI / RAG 系统

  1. 对 Vibe Coding 了解吗?平时使用什么框架或工具?在使用这些 AI 工具生成代码的过程中,你遇到过什么问题?
  2. 假如用户提出恶意问题(提示词攻击),比如要求删除知识库文档,你如何避免这种恶意操作?
  3. 自动问答知识库系统(RAG)中,为什么要用 BM25 和向量混合索引?基于什么考虑?
  4. 你怎么样评估你的 RAG 系统的好坏?应该做哪些测试?提交给决策者做可行性分析可以给出哪些数据?
  5. 如果用户问了 A 问题,预期 A 答案,但始终得到错误答案,你怎么样去定位排查这个问题?

反问

  1. 做的业务主要是什么?技术栈是什么样的?
  2. 实习生培养机制大概是怎样的?
  3. 真实的业务开发中,是否有用到 AI 技术?是怎么使用的?

参考解析

Q4 & Q8:系统扩容与秒杀应对

  • 单机 Redis + 本地缓存通常可支撑 1k~5k QPS;1 万 QPS 需考虑:Redis 集群、本地缓存预热、数据库读写分离 + 分库分表、接入层水平扩容。
  • 秒杀瞬间流量是正常流量的数倍,核心手段:前端限流(按钮防重)→ 网关限流 → 队列削峰 → Redis 原子扣减库存 → 异步写 DB,避免流量直接打穿数据库。

Q9 & Q29:滑动窗口 vs 固定窗口

  • 固定窗口在窗口边界可能出现 2 倍突刺(前后窗口各打满),滑动窗口通过时间分片或 Redis ZSet 实现,统计任意连续时间段内的请求数,流量更平滑。
  • Redis 实现:ZADD key timestamp member + ZREMRANGEBYSCORE 清除过期成员 + ZCARD 计数,整个操作用 Lua 保证原子性。

Q12 & Q13:Redis Lua 脚本阻塞问题

  • Redis 是单线程执行命令,Lua 脚本执行期间其他命令全部阻塞。若脚本耗时 10~20 秒,会导致所有客户端超时、连接积压、系统雪崩。
  • 对策:脚本必须精简,避免循环大量 KEY;设置 lua-time-limit(默认 5s)超时保护;开发阶段充分测试脚本逻辑。

Q15:Caffeine 淘汰策略

  • Caffeine 使用 W-TinyLFU 算法:结合 LRU(应对新数据)和 LFU(应对高频数据),用 Count-Min Sketch 频率草图节省内存。相比 Guava Cache 的纯 LRU,命中率更高。

Q26:双缓存不一致处理

  • 典型场景:更新 DB → 删除/更新 Redis → 但 Caffeine 还持有旧值(TTL 未到)。
  • 解决方案:① 设置 Caffeine 较短 TTL(如 5~30s);② 通过消息(MQ 或 Redis Pub/Sub)广播本地缓存失效;③ 业务上允许短暂不一致时,依赖 TTL 自动过期即可。

Q17:在线大表加索引注意事项

  • MySQL 5.6+ 支持 Online DDLALGORITHM=INPLACE, LOCK=NONE),加索引期间不阻塞读写,但仍消耗 IO。
  • 生产建议:① 低峰期执行;② 使用 pt-online-schema-changegh-ost 工具;③ 提前监控主从延迟,避免从库延迟过大影响读请求。

Q22:主从数据一致性

  • MySQL 主从通过 binlog 异步/半同步复制。完全一致难以保证(异步复制存在延迟)。
  • 实践策略:① 强一致读强制走主库(如支付查询);② 普通读允许短暂延迟走从库;③ 使用半同步复制减少延迟;④ 读从库前可检查 seconds_behind_master

Q31:CAS 与 ABA 问题

  • CAS(Compare And Swap):比较内存值与预期值相等才更新,无锁,但存在 ABA 问题:值从 A→B→A,CAS 无法感知中间变化。
  • 解决:使用 AtomicStampedReference 引入版本号/时间戳,每次修改版本号递增,CAS 同时比较值和版本号。

Q33:死锁排查

  • 死锁四个必要条件:互斥、持有并等待、不可剥夺、循环等待。预防:固定加锁顺序、使用超时锁(tryLock)、减小锁粒度。
  • 排查:jstack <pid> 输出线程快照,搜索 deadlock 关键字;或使用 Arthas thread -b 直接定位阻塞线程。

Q34:equals 与 hashCode

  • == 比较引用地址,equals 默认也是引用比较,重写后比较逻辑相等性。
  • 约定equals 相等的对象 hashCode 必须相同。若只重写 equals 不重写 hashCode,放入 HashMap/HashSet 时会因 hash 不同导致找不到对象,破坏集合语义。

Q37:RAG 混合检索(BM25 + 向量)

  • 向量检索:语义相似度强,能捕捉同义表达,但对精确关键词匹配弱。
  • BM25:词频统计,擅长精确关键词、专有名词召回。
  • 混合索引结合两者优势,通过 RRF(倒数排名融合) 或加权合并召回结果,提升整体召回率和精度。

Q38 & Q39:RAG 系统评估与排查

  • 评估指标:召回率(Recall@K)、精确率、RAGAS(Faithfulness、Answer Relevancy、Context Recall)、端到端 E2E 准确率。
  • 排查错误答案链路:① 检查问题是否命中正确 chunk(检索层);② chunk 命中但答案错误 → 生成层问题(Prompt 设计或模型幻觉);③ 未命中 → 索引缺失或向量质量差,考虑优化 embedding 或补充文档。