字节跳动后端一面:Agent 项目、代码审查与客服系统设计
- 轮次
- 一面
- 时间
- 2026-09
- 来源
- 牛客网
《面试题目》
- 自我介绍。哪个项目参与最深?介绍第一个实习 Agent 项目和个人工作。
- 项目最难或最亮眼的地方是什么?方案为何这样定?
- 错召回、漏召回解决了吗?效果多少?
- 第一个实习的离职原因是什么?
- 代码审查:审查”DB 查工单并缓存”的代码,有什么问题?
- 一批优惠券怎么保证每人限领一张,同时不超发?
- 代码审查:审查 Java 转账代码,有什么并发与原子性问题?如果给转账加事务,怎么加?
- 何时需要分布式事务?有哪些方案?
- 有 AI Coding 工具后,程序员还要会写代码吗?
- 从零设计云产品智能客服:知识、资源、排障和转人工。
- 算法题:岛屿数量。
- 有哪些主动发现、推动并落地的问题?之前的性能问题是怎样发现并推进解决的?
《参考解析》
查工单并缓存这类代码常见的问题:① 缓存穿透——不存在的工单 ID 每次都查库,需要空值缓存或布隆过滤器;② 缓存与数据库不一致——先更新库再删缓存/先删缓存再更新库,两种顺序都有并发窗口,正确做法是”更新 DB 后删除缓存 + 延迟双删”或用版本号/订阅 binlog 失效;③ 无过期时间或过期时间过长,数据变更后长时间不一致;④ 缓存 key 设计过粗或过细,导致命中率低或内存膨胀;⑤ 缺少降级——缓存不可用时是否直接打库、要不要限流;⑥ 大 key(如把整个工单列表塞一个 key);⑦ 未处理并发回源,热点 key 需要 singleflight 合并。
优惠券限领不超发:核心是把”检查 + 扣减”做成原子操作,别信应用层的判断。三层设计:① 库存预扣用 Redis Lua 原子脚本(判断库存 > 0 再 DECR),或直接落库用 UPDATE stock SET left = left - 1 WHERE id = ? AND left > 0 判断受影响行数;② 每人限领靠数据库唯一索引 (activity_id, user_id) 直接约束——这是最可靠的一层,重复插入必然失败;③ 异步落库时靠幂等键避免重复扣。高并发下还可以把库存分桶(把 1000 张券拆成 10 个 key 各 100 张)降低热点争抢。要强调”唯一索引是最后防线”,应用层的查询判断只是为了减少无效请求。
转账代码的并发与原子性问题:常见几类——① 检查余额与扣减分离,两个线程都读到足够余额造成超扣(需要 UPDATE ... SET balance = balance - x WHERE balance >= x 或行锁);② 两笔转账互相持锁造成死锁(要固定加锁顺序,如按账户 ID 排序);③ 只做了单边更新,异常时另一半没执行,破坏一致性(必须放在同一个事务里);④ 用 double 存金额导致精度问题(应该用 DECIMAL 或整数分);⑤ 事务里做远程调用导致长事务持锁(应该把远程调用移出事务,用状态机 + 补偿);⑥ 缺少幂等,重复提交会转两次。
加事务的正确姿势:用 @Transactional 时要注意自调用失效(同类内部调用不走代理)、异常被吞导致不回滚(只有非受检异常默认回滚,需要显式指定 rollbackFor)、事务内 select 的隔离级别选择,以及事务粒度要小(不要包住网络 I/O)。如果是并发扣款场景,配合悲观锁(SELECT ... FOR UPDATE)或乐观锁(版本号)来防超扣。
什么时候需要分布式事务:当一次业务操作跨多个独立的数据源(多库、多服务各自的本地事务)且需要保证整体一致时。方案有 2PC/XA(强一致但性能差、有同步阻塞)、TCC(业务侵入强,需要写 Try/Confirm/Cancel 三个接口)、Saga(长事务补偿,适合链路长的业务流程)、本地消息表 + MQ(最终一致,最常用)、以及基于事务消息(RocketMQ)的方案。工程上优先考虑”能不能通过业务设计避免分布式事务”——比如把两个操作合并到同一个服务/同一个库,或者接受最终一致并做好对账。
AI Coding 时代还要不要会写代码:要,而且判读能力变得更值钱。AI 提升的是产出速度,不改变正确性的标准——你仍然要能判断它给的方案对不对、边界是否覆盖、性能与安全是否有坑。真正的变化是”人从写转到审”,所以读代码、拆问题、定义验收标准的能力权重上升;反过来,只会照抄实现、说不清为什么这样写的岗位会被压缩。
云产品智能客服的系统设计:分四块。① 知识层——把文档、FAQ、工单历史、产品配置建成可检索知识库,做好元数据(产品线、版本、生效时间、权限)与版本隔离;② 资源层——用户/租户信息、订单/实例状态等实时数据通过工具调用获取,不由模型生成;③ 排障层——定义可执行的诊断流程(查状态、看日志、比对配置),用工作流编排,把”诊断结论 + 证据”输出给人;④ 转人工——设置明确的升级条件(置信度低、用户情绪、涉及资金或不可逆操作、连续两轮未解决),转接时带上完整上下文避免用户重复描述。工程上还要有:权限与数据隔离、敏感信息脱敏、成本与限流、全链路可观测,以及一套覆盖”无答案/知识过期/工具失败”的评测集。
岛屿数量:DFS/BFS 遍历二维网格,遇到 '1' 就让计数器加一,然后把它所在整片连通区域全部标记为 '0'(或访问过)。每个格子最多进出一次,时间 O(mn)、空间 O(mn)(最坏递归栈)。数据量大时用显式队列做 BFS 或并查集(并查集还能顺便处理动态加陆地的问题)。