面灵AI→

字节跳动 AI 全栈实习一面(中国交易与广告):多 Agent 编排与 Redis 定位

轮次
一面
时间
2026-10
来源
牛客网

《面试题目》

  1. 面试官介绍此次面试时长和流程。
  2. 自我介绍。
  3. 你了解我们这个部门吗?这个岗位大概是怎么样?
  4. 实习时长和出勤时长?什么时候能到岗?
  5. 介绍一下项目 1。
  6. 输入是什么?多 Agent 怎么编排?
  7. 是面向内部还是面向用户?是一个 skill 的形式让大家用的吗?
  8. 介绍一下项目 2。
  9. 这个项目的必要性在哪里?现在大模型和智能体感觉已经能做了吧?
  10. 好,下面我要问你一些基础题,就问你一些数据库相关的可以吗?
  11. 用什么数据库?
  12. Redis 在项目 2 里做什么?
  13. 如果自己做着玩,Redis 确实可以做消息队列和任务队列,但是你知道 Redis 主要做什么吗?
  14. 了解 MySQL 的索引类型吗?有什么底层?
  15. 介绍一下 B+ tree。
  16. 你知道什么是回表吗?
  17. 知道什么是 MVCC 相关的东西吗?
  18. 给一个场景:10 亿条 URL,但是只有 1GB 内存,怎么找出 top100 的 URL?
  19. 手撕:合并重复区间。
  20. 反问。

《参考解析》

多 Agent 编排:输入、角色、协作方式要答清楚

被问「输入是什么、多 Agent 怎么编排」,要把编排讲成有明确契约的结构。先说输入形态:是自然语言目标、结构化参数,还是两者的组合;再说角色划分——常见做法是「规划者(拆解任务)+ 执行者(调用工具/检索)+ 校验者(检查结果与格式)」,每个角色只负责一件事,通过结构化消息(JSON)传递中间结果而不是自由文本,这样每一步都能校验、能重放。编排形态上要区分固定工作流与动态规划:固定流程(DAG)稳定、可观测、容易限流,适合步骤确定的场景;动态规划灵活但会漂,所以要限制可用工具白名单、最大步数、超时与预算,并设计失败回退(重试、换路径、交回人工)。协作的工程细节包括:共享状态放哪(一个显式的 state 对象比让 Agent 互相读对话历史可靠)、并发与顺序(能并行的子任务并行、有依赖的串行)、以及全链路 trace——每一步用了什么输入、调了什么工具、耗时多少,出问题时能回放。最后补一句取舍:Agent 越多协调成本越高,能用单次调用 + 工具链解决的就别拆成多 Agent。

「这个项目有必要吗,现在大模型是不是已经能做了」

这类质疑式问题的答法是把「模型能做」和「系统能稳定交付」分开。模型能做的是语义理解与生成,做不了或做不稳的是:确定性规则与权限边界(哪些数据能碰)、结果的可靠性与可复现(同样输入要给出同样结论)、成本与延迟控制、以及可审计。项目存在的必要性通常来自三件事之一——把专业知识沉淀成可检索的资料(否则模型只会给通用答案)、把重复流程自动化(人只在关键节点确认)、以及把结果落到既有系统里(工单、报表、审批流)。答题时最好举一个具体对比:没有这个系统时某件事要多久、错在哪里,有了之后变成什么样,用数字说明,比争辩「模型能不能做」有效。

Redis 的定位与 MySQL 索引、B+ 树、回表、MVCC

「Redis 主要做什么」这题的关键词是内存数据库与缓存,要压过「消息队列」。它的本职是高性能的键值存储:缓存热点数据降低数据库压力、做会话与 token 存储、计数与限流(INCR、令牌桶)、排行榜(ZSet)、分布式锁(SET NX PX + Lua 释放)、去重与布隆过滤器、以及地理位置(GEO)。消息队列可以用 List/Stream 实现,但缺少专业 MQ 的持久化保障、堆积能力与消费组语义(Stream 补齐了一部分),所以选型的判据是能不能接受丢与要不要顺序:能接受丢、量不大可以用 Redis,要求可靠投递与堆积能力就用 Kafka/RocketMQ。要顺带讲清 Redis 的代价与陷阱:内存成本、持久化(RDB/AOF)在故障时可能丢窗口内的数据、单线程模型下慢命令会阻塞(大 key、keys *、hgetall 大 hash),以及主从/集群下的一致性与热点分片。

MySQL 索引从数据结构分有 B+ 树(默认,最通用)、哈希(Memory 引擎、等值查询)、全文索引,从功能分有普通索引、唯一索引、主键(聚簇)、联合索引、前缀索引。InnoDB 的 B+ 树:非叶子只存键与页指针,扇出大、树高通常三到四层;数据全在叶子节点且叶子之间用双向链表相连,因此范围查询和排序高效;所有查询都要走到叶子,路径长度一致、性能稳定。回表是二级索引查到主键后再去聚簇索引取完整行的过程——想避免就做覆盖索引(查询列都在索引里),或者把常用列放进联合索引。MVCC 是多版本并发控制:每行记录带隐藏的 DB_TRX_ID(最近修改事务)与 DB_ROLL_PTR(指向 undo log 旧版本),读时通过 Read View 判断版本可见性,从而实现「读不加锁、读写不阻塞」。RC 与 RR 的差别就在 Read View 生成时机:RC 每次快照读都新建 Read View(所以能读到别人的提交),RR 只在事务内第一次快照读时生成并复用(所以可重复读),RR 下靠间隙锁(Next-Key Lock)防幻读。答题时说清「undo log 保存旧版本 + Read View 判断可见性」这两点,基本就到位了。

10 亿条 URL、1GB 内存找 Top100

这题考点是分治加上小顶堆。URL 总量远超内存,所以不能全部装进哈希表(1GB 内存装不下 10 亿个字符串)。标准解法两步:第一步哈希分片——对每个 URL 取哈希后模 N(比如 1024),追加写到 N 个小文件里,同一个 URL 一定落在同一个文件,因此每个文件内的重复项可以独立统计;第二步逐文件处理——对每个小文件用哈希表统计词频(此时单个文件规模已能装进内存),维护一个大小为 100 的小顶堆,堆顶是当前第 100 名,新的频次比堆顶大就替换并调整堆;最后把 N 个文件的 Top100 合并(最多 N×100 个候选),再用一次小顶堆得到全局 Top100。要主动说的细节:选 N 的依据是让每个分片能装进内存(可以按 总量×平均长度/内存 估算,不够就增大 N 或改成多轮);哈希要避免倾斜(可以用更好的散列或加盐),倾斜严重时个别分片仍装不下,可以对该分片再分一次。可以补一个变体:如果允许近似结果,用 Count-Min Sketch 加堆能在更小内存下给出近似 TopK,代价是有误差;如果能用多机,就直接把分片分到不同机器上并行。面试官追问「为什么用小顶堆而不是大顶堆」时答:小顶堆的堆顶是当前候选里最小的,新元素只要比它大就能替换,空间固定为 K。

手撕:合并重复区间

标准做法是先按区间起点排序(O(n log n)),再一次线性扫描:维护当前区间,若下一个区间的起点小于等于当前区间的终点则合并(终点取两者的较大值),否则把当前区间推入结果并开始新区间。要主动说清的细节:排序是必需的(否则要处理乱序);合并条件用 <= 还是 < 取决于是否认为端点相接算重叠(要跟面试官确认,比如 [1,3] 与 [3,5] 是否合并);输入为空或只有一个区间要能正常返回;如果区间已经有序可以省掉排序。写完之后用一个小例子跑一遍(比如 [1,3],[2,6],[8,10],[15,18] 得到 [1,6],[8,10],[15,18]),展示你能自测。追问常见延伸:如果要合并的是「时间区间且规模极大」,排序依然是瓶颈,可以考虑分桶或对已排序的数据流做在线合并。