面灵AI→

字节跳动 抖音电商 Java后端 日常实习面经(三面 + HR)

轮次
三面
时间
2026-09
来源
牛客网

《面试题目》

一面(约 1 小时)

  1. 自我介绍;你做过的几个项目里,哪个最有挑战?为什么?
  2. RAG 智能知识库主要解决什么问题?具体应用场景是什么?(是给模拟面试使用,还是独立知识库功能?学习小组具体怎么使用?)
  3. RAG 知识库和大模型是怎么连接的?完整请求链路是什么?(用户问题从哪里进入?用户是在和 Agent 对话,还是直接和大模型对话?你的系统到底属于 Agent、Workflow 还是 Skill?)
  4. RAG 的整体检索流程是什么?
  5. 决策机制具体是怎么设计的?
  6. 简历上的优化是怎么做的?
  7. 优化的 P50 / P95 数据是怎么测出来的?
  8. 平时使用过哪些大模型?最近主要使用哪个模型?学校对使用这些 AI 工具是什么态度?
  9. 优惠券管理系统主要做了什么?核心业务是什么?是不是优惠券秒杀场景?用户抢的券本身是否有价格?
  10. 优惠券秒杀完整链路是怎么实现的?Redis Lua 如何校验库存和用户领取次数?Redis 如何预扣库存?用户券如何缓存和过期?
  11. 商家创建 CouponTemplate 之后,C 端用户怎么知道有哪些优惠券可以领取?
  12. Redis 中优惠券列表和优惠券模板具体怎么组织?
  13. 优惠券查询出现热点 Key 怎么处理?某个热门商家被大量用户查询怎么办?某张秒杀券一百万用户同时访问怎么办?
  14. Redis Lua 预扣成功,但是 RocketMQ 消息发送失败怎么办?
  15. 这个优惠券项目是真实业务项目还是学习项目?有没有实际用户使用?
  16. 场景编程题:知识库文档多路结果合并。
  17. 智力题:两根不均匀燃烧、每根烧完需要 60 分钟的绳子,怎么计时 45 分钟?
  18. 反问:团队具体负责什么业务?

二面(leader,约 1 小时)

  1. 自我介绍。
  2. 项目是如何规划的?为什么要做这些项目?想要学习什么?
  3. 讲一个以前完全不了解的技术点,如何从零开始学习之后掌握的?
  4. 除了 RAG,大模型 / Agent 相关的技术有学习过哪些?agent 具体学习了什么?
  5. skill 发现机制是如何实现的?
  6. 自己学习过程中写过什么 skill 吗?code 使用过程中是否沉淀过一些 skill、是否用过其他人的 skill?
  7. skill 不适合干什么?skill 出现了之后为什么还是需要 MCP?skill 也能够调用脚本,skill 和 MCP、tool 的根本区别是什么?
  8. tool 和 skill 你在实际开发过程中使用过吗?有写过相关 demo 吗?
  9. Agent 三种范式你有自己写过相关 demo 吗?
  10. AI 相关知识更新很快,你觉得当前哪些做法能较好应对这种快速更新?
  11. harness 概念你知道吗?
  12. codex 过程中你认为你使用的是哪种 engineering 模式?测试用例执行过程中是否遇到过问题?
  13. Spec Coding 是否了解?
  14. 优惠券管理系统是个 demo 吗?你说为了学习高并发相关内容,具体是什么链路呢?
  15. 秒杀一般会对系统带来什么问题?
  16. 热点 key 问题如何解决?
  17. Java 中反射概念知道吗?
  18. IoC 是什么?解释下。IoC 有什么好处?我不用 IoC 不也能复用单例吗?IoC 本身和 Spring 是强绑定的吗?
  19. 目前实习计划?
  20. 算法题:LC 打家劫舍。
  21. 多线程代码阅读(银行扣减防止超卖):哪些代码导致了这个扣减的问题?怎么改?synchronized 加在哪里?除了 synchronized 还有什么实现方式吗?
  22. 假设代码中可以使用 MySQL、Redis,你会怎么实现?可以只用 MySQL 实现吗?
  23. 反问技术栈、面试轮数。

三面(约 33 分钟)

  1. 自我介绍。
  2. 目前是大三的话,学校学习了什么课程?
  3. 说说你对操作系统的理解,我希望是体系化的介绍,代表你对整个课程的理解。
  4. 给你一个 url 链接你会想到什么?
  5. 什么是 DNS 污染?
  6. 项目经历里面你做了什么?是领券功能还是抢券功能?库存扣减你是怎么做的?
  7. 通过项目实践,你收获了什么?
  8. Leetcode 下一个排列。
  9. 当前你的实习计划是什么样的?
  10. 反问:组里整体氛围是什么样的?结果什么时候会出?实习生的要求以及建议?

HR 面

  1. 自我介绍。
  2. 确认基本信息:目前大几、预计什么时候毕业?
  3. 接下来一年的学业安排是什么样的?还有哪些课程?一周大概有多少课?后续有没有毕业论文、毕设等安排?
  4. 如果实习 base 不在学校所在地,课程怎么安排?学校是否支持长期实习?是否可以请长假?下学期是否也可以继续请假实习?
  5. 下一段实习怎么规划?大概什么时候可以开始实习?希望实习多久?
  6. 为什么计划实习六个月以上?六个月之后是准备回学校做其他事情,还是可以继续延长?最长大概可以实习多久?
  7. 找实习找了多长时间了?
  8. 目前面试过哪些公司 / 岗位?哪些已经走到比较靠后的流程?
  9. 为什么拒掉已经拿到的其他机会?
  10. 选择要不要面一个岗位、以及拿到 Offer 后要不要接,最看重哪些因素?如果选最重要的三个因素,怎么排序?
  11. 你所说的「有挑战的业务」具体是什么样的?
  12. 两个项目里,你觉得哪个更有挑战?项目背景是什么?是课程项目、个人尝试还是其他项目?遇到了什么难点?最后是怎么解决的?
  13. 这个项目是你自己一个人独立闭环完成的吗?
  14. 如果让你重新做一次这个项目,会在哪些地方做调整或改进?怎么让开发过程更高效?怎么让最终效果更好?
  15. 在学校期间,老师或同学对你的高频评价是什么?如果总结成 1~3 个关键词,会是什么?
  16. 你对下一段实习有什么期待?如果实习六个月甚至更久,希望最终获得什么样的成长和成果?
  17. 关于博客 / 技术文章:做博客大概多久了?最开始为什么想做博客?坚持写博客过程中有哪些思考和收获?
  18. 反问:从 HR 的角度对实习生有什么建议或者要求?HR 面之后的整体流程是什么样的?结果大概什么时候出来?Base 地怎么考虑?

《参考解析》

  1. 秒杀完整链路:整条链路的目的是把流量挡在数据库前面。请求进来先在网关或应用层做限流和防刷(同一用户、同一设备的频次),然后用 Redis 做库存预扣。预扣必须用 Lua 脚本,因为它把「读库存 → 判断是否充足 → 判断用户是否已领 → 扣减 → 记录领取」这几步合成一次原子执行,Redis 单线程执行脚本期间不会被打断,天然免疫并发。扣减成功之后不要同步写订单库,而是发一条 MQ 消息异步落库、异步发券,接口立刻返回「排队中」,前端轮询或推送结果。这样数据库承受的是削峰之后的写入量。
  2. Lua 预扣成功但 MQ 发送失败怎么办:这是这道题的真正考点——本地操作已经生效、下游投递失败了。要分两种情况看。如果在事务里,可以用本地消息表:扣减和「写一条待发送消息」放在同一个本地事务里,再由定时任务扫表补发,靠消息表的唯一索引保证不重复发。如果用 RocketMQ,可以用事务消息,先发半消息、执行本地事务、再提交或回滚。如果只是单机无事务,最省事的是「先写消息表再扣减」或者扣减后立刻记录一条补偿记录,总之原则是不允许出现「Redis 已经扣了但没有任何地方记得要补」的状态。兜底还要有对账任务,按券的发放流水和订单表比对,把差异捞出来人工或自动修。
  3. 热点 key 怎么处理:先确认热点的粒度。如果是单张秒杀券被百万用户同时访问,那把库存拆成 N 份分片(比如 100 份),请求按用户 ID 哈希落到某个分片扣减,各分片独立执行 Lua,最后汇总;这是「库存分桶」。如果是商家维度的读热点,就在本地缓存(Caffeine)加一层,或者给 key 加随机后缀把读请求打散到多个副本上再聚合。另外要注意热 key 的探测本身——不是等它出问题才知道,而是靠客户端埋点统计 key 的 QPS,超过阈值就用 --hotkeys 或 MONITOR 采样确认,然后把这个 key 推进本地缓存。
  4. 银行扣减超卖的代码怎么改:那道题的核心是「检查—执行」不是一个原子操作,if (!paid(orderId)) 和 markPaid(orderId) 之间可能被其他线程插入,也可能被同一条线程的另一次调用重入。改法分几层。单机用 synchronized 的话,锁要加在稳定的共享对象上,加在方法上锁的是 this,如果 service 是多例、或者有多个实例,就完全锁不住;更稳的是按 orderId 分段加锁(ConcurrentHashMap + 每 key 一把锁,或 striped lock)。分布式场景要用 Redis 的 SET NX PX 或者数据库乐观锁(带 version 或状态字段的 update ... where status = ?),并且把「查状态 → 改状态」收进一条带条件的 SQL 里,用影响行数判断是否抢到。除此之外还要考虑幂等:同一笔支付请求重试时不能重复扣钱,所以要有业务唯一键。
  5. 只用 MySQL 能不能实现:能,而且不少真实系统就是这么做的。用 update coupon set stock = stock - 1 where id = ? and stock > 0 这一条语句,靠 InnoDB 的行锁保证原子性,影响行数为 1 就是扣减成功。它的优点是实现简单、不用维护 Redis 一致性,缺点是高并发下所有请求争同一行锁,会串行排队,QPS 上不去(单行热点更新的上限大概就是几千)。所以选型看量级:几千 QPS 以内 MySQL 足够;到了几万、几十万就得引入 Redis 预扣把流量卸掉这一层。
  6. skill、MCP 和 tool 的区别:这三者经常被混着问,区别在抽象层次和加载方式。tool 是最小执行单元,一个函数加一份 JSON Schema,模型决定什么时候调用它。MCP 是协议,解决的是「工具怎么接进来」——把外部系统(数据库、文件系统、第三方 API)按统一协议暴露成一组工具,好处是接入和模型解耦、可以复用。skill 更偏「领域知识和流程的封装」,它描述的是「这类任务该按什么步骤做、要注意什么」,往往内含多个 tool 调用、也可能带脚本和参考资料,通常在需要时才按描述被加载进来,所以能省上下文。一句话概括:tool 是动作,MCP 是动作的接口标准,skill 是把一串动作加判断条件打包成的作业指导书。
  7. 两根绳子计时 45 分钟:第一步,同时点燃第一根绳子的两头和第二根绳子的一头;第一根烧完时正好过去 30 分钟,此时第二根还剩 30 分钟的「单头燃烧量」。第二步,立刻把第二根的另一头也点上,它剩下的部分两头同时烧,15 分钟烧完。总计 45 分钟。关键理解是「不均匀」不影响结论:两头同时烧一定是用时的一半,因为两团火无论在哪里相遇,消耗掉的总长度都是整根。
  8. 联合索引 (a, b) 和 (b, a) 的差异:最左前缀原则决定了两者能支持的查询不同。where a = 1 能用 (a, b),用不了 (b, a);where a = 1 and b = 2 两者都能用,差别在数据分布不好时 (a, b) 可能先按 a 定位到很大一片再过滤 b,而 (b, a) 反过来。真正会出现「同样的条件却选了另一个索引」的情况,往往是优化器根据统计信息估的行数不同,或者某个索引是覆盖索引(要查的列都在索引里就不用回表,成本天然更低)。count(*) 和 count(具体列) 的区别是前者不判断 NULL、能走最小的二级索引,后者要读出那一列再判断非空,所以一般 count(*) 更快;而 count(*) 配 a = 1 and b like '%name' 这种,b 上的前导通配符会让它没法走索引,只剩 a 能用。
  9. P50 / P95 这类指标怎么测出来:压测工具(JMeter、wrk、k6)跑出带分位的报告,或者生产上从埋点日志里按时间窗口聚合。关键是说清楚三件事:测的是什么环境(本地 / 预发 / 线上灰度)、样本量和持续时间、以及分位数是从什么粒度统计的(单机还是全链路)。如果简历上写了「优化后 P95 从 800ms 降到 200ms」,要能补上「用 200 并发压 10 分钟、取后 5 分钟的稳定值」这种细节——考官问这一句,考的就是这个优化是不是真的做过。
  10. RAG 的完整链路和「决策机制」:链路本身是「文档解析与切分 → 向量化入库 → 查询改写 → 召回(向量 + 关键词混合)→ 重排 → 拼 prompt → 生成」。被问「决策机制」时,通常是指召回之后怎么决定给模型哪些内容:常见做法是设分数阈值过滤低相关内容、按来源去重并限制同一文档的片段数量、再按 token 预算截断。真正能加分的回答是补上「我为什么这么定」——比如阈值太松会把噪声喂进去导致答非所问,太紧则召回率掉下来,所以用一批标注问题扫了一遍阈值取 F1 最高的点。混合检索的收益也要能说出量化的提升,不然就只是「我用了两种检索」。