字节国际化广告后端实习一二面凉经:Coding Agent 与 RabbitMQ
- 轮次
- 一二面
- 结果
- 挂
- 时间
- 2026-09
- 来源
- 牛客网
《面试题目》
一面
- 自我介绍。
- MySQL 怎么保证事务中的操作全部成功或全部失败?undo log 和 redo log 有什么区别?redo log 的底层机制是什么?
- 如果让你设计 Agent 的短期记忆和长期记忆,你会怎么做?怎么处理记忆的遗忘和过期?
- 你自己做的 Coding Agent 与普通的通用 Agent 有什么区别?
- 子 Agent 是怎么实现的?在一个会话里,Agent 怎么创建一个子 Agent,又怎么管理它?
- Agent 执行复杂任务时可能耗时很长、步骤很多,如果中间出错、退出或者中断,应该怎么处理?
- 你的 Agent 怎么防止陷入死循环?
- 我看你的项目都是从今年三月份开始做的,之前没有做过其他事情吗?
- MySQL 和 Elasticsearch 有什么区别?两者的索引有什么区别?
- 现在有一个联合索引 (A, B),查询条件是
B=1 AND A=2,对于 MySQL 来说,能利用这个索引吗?为什么这样写查询条件也能利用? - 算法:K 个一组反转链表的变种题(不足 k 个也要反转)。
- 反问。
二面
- 什么是数据库的联合索引?使用联合索引时有什么需要注意的地方?
- 讲一下你的 Coding Agent 项目。有评测过吗?如果让你评测,可以从哪些角度出发?稳定性怎么测?
- 你这套是单 Agent 的,对吧?多个 Agent 之间的上下文,你是怎么协调的?
- 你有哪些子 Agent?代码审查这类 Agent 需要特殊的上下文处理吗?具体怎么做?
- 谁来告诉代码审查 Agent 要检查什么、达到什么效果?
- 可以无限创建子 Agent 吗?子 Agent 可以再创建自己的子 Agent 吗?为什么不允许?
- 如果允许子 Agent 创建子 Agent,怎么防止无限递归?如果允许递归深度大于 2,应该怎么防止?
- 这是你的 Harness 应该处理的逻辑,为什么要交给根 Agent 判断?
- 如果几个子 Agent 形成死循环,比如三个工具互相调用、谁都停不下来,你怎么让它们及时停止?你怎么感知循环调用?怎么区分合理的循环调用和死循环?什么时候应该把它们喊停?
- 你这套方案与直接使用 Codex 相比,有什么优势?
- 你的项目亮点是什么?
- RabbitMQ 的生产消费模型是怎样的?消费失败了怎么办?有死信队列之类的设计吗?这是 RabbitMQ 自带的死信队列吗?死信队列最多能接受多少条消息、有上限吗?如果需要重试的消息超过了死信队列的最大容量,应该怎么设计?
- 算法:十六进制大数相乘。
《参考解析》
redo log 与 undo log 的分工。undo log 记的是”数据修改前的旧值”,用于回滚和 MVCC 读旧版本,逻辑日志、按行记录;redo log 记的是”数据页上做了什么物理修改”,用于崩溃恢复,物理逻辑日志、顺序写、固定大小循环复用。事务提交时写 redo(WAL,先写日志再刷盘)保证持久性,回滚时用 undo 保证原子性。底层机制上,redo 采用环形缓冲区 + checkpoint:LSN 单调递增标记进度,checkpoint 之前的日志可以被覆盖,崩溃恢复时从 checkpoint 往后重放。
子 Agent 的创建与递归边界。主流实现有两种:一是”进程 / 会话级隔离”,子 Agent 是独立上下文的新会话,根 Agent 只拿到它的最终输出;二是”同一会话内的角色切换”,共用部分上下文但用不同的系统提示与工具集。管理的核心是三件事:生命周期(何时创建、何时回收,避免会话泄漏)、上下文传递(子 Agent 需要哪些信息,只传必要的最小集,否则 token 成本失控)、结果归并(子 Agent 的输出要不要结构化、根 Agent 怎么判断它是否可信)。递归一定要设硬上限,理由是组合爆炸与不可控:每层都可能失败重试,深度一放开,成本、时延、状态一致性都失去可预测性。防无限递归的手段是限制深度 + 全局预算(步数 / token / 时长)+ 调用指纹去重,且这些限制应该由 harness 在工具调用层强制执行,而不是”交给根 Agent 自己判断”——模型可能被诱导、也可能判断错,把安全边界交给被约束对象本身是不成立的。
死循环的判定与停止。硬约束三件套:最大步数、最大 token、整体超时。软判定有三类信号:状态重复(把关键状态归一化后取指纹,连续出现同一指纹说明原地打转)、调用指纹重复(同工具同参数连续调用 N 次)、进展为负(同一子目标连续失败、错误信息不再变化)。区分”合理的循环”与”死循环”要看是否产生新信息:轮询等待外部状态变化、逐条处理列表这类循环,每轮输入在变、进度在推进,是合理的;反复读同一文件、反复调同一接口且参数不变,才是死循环。喊停的时机可以定成”同一指纹第三次出现就中断并降级收尾”,并把已完成步骤与卡点一并交回。
Coding Agent 的评测角度。可分四层:任务完成度(能否通过预先写好的测试、编译是否通过、lint 是否干净)、过程质量(改动文件数、diff 行数、是否绕开问题去打补丁、有没有留下调试代码)、稳定性(同一任务重复跑多次的成功率与方差,比单次成功更重要)、成本与时延(token 消耗、工具调用次数、wall time)。稳定性测试尤其重要,因为 Agent 的失败往往是概率性的,只跑一次通过说明不了问题。
MySQL 与 Elasticsearch 的索引差异。MySQL 默认是 B+ 树,索引与数据同源、支持事务与强一致,擅长按精确值和范围做低延迟点查与范围扫描,写入时还要维护二级索引,代价高;ES 是倒排索引 + doc_values 列存,按词项建 posting list,擅长全文检索、相关性打分与聚合分析,写入是近实时的(refresh 才可见),事务与强一致不是它的目标。选型上常见组合是”MySQL 存权威数据、ES 做检索”,通过 binlog 同步,接受秒级延迟。
死信队列的容量与溢出。RabbitMQ 的死信队列本质是一个普通队列——它没有特殊容量上限,受内存、磁盘和 max-length / TTL 等策略约束。也就是说”死信队列能装多少”取决于你给这个队列配了什么策略,不配就是不设限但可能把 broker 撑爆;配了 x-max-length 就会按策略丢弃或拒绝。所以设计上应该主动给它设上界,并且超过容量要有明确归宿:常见做法是死信队列只作”人工排查入口”,容量较小 + TTL 较短,溢出的消息落到数据库或对象存储里留档,再由定时任务按分类重放。重试本身要分级——用多级延迟队列做递进退避(1min / 5min / 30min),超过最大重试次数才进死信,同时记录失败原因,避免”重试风暴”打垮下游。