字节后端面经:广告去重、知识图谱发布与 Saga 补偿
- 时间
- 2026-09
- 来源
- 牛客网
《面试题目》
后端开发,9 月 3 日
- 面对十亿级用户、百万级广告,如何以较低内存成本实现广告曝光频控和去重?
- 是否需要为每个用户维护 RoaringBitmap,百万级广告怎样容纳?
- 如果用 ZSet,以广告 ID 为 Key 时用户维度怎样保存?以用户 ID 和日期为 Key 时又怎样保存广告和判重?
- 平时主要写 Go 还是 Java?
- 基于 RAG 的 Agent 可以从哪些方面提升召回质量和最终效果?
- Kafka 怎样做负载均衡,10 个消费者实例中有 3 个宕机时会发生什么?
抖音电商开发,9 月 3 日
- 实习什么时候开始,两个多月主要负责知识图谱平台的哪些工作?
- 原有系统使用 RAG 还是知识图谱,接口背后是业务系统还是文档检索,是否替换了原知识库?
- 多文档关联检索具体是什么?
- “字节跳动公司”“北京字节跳动公司”“字节跳动”等实体如何去重,怎样防止误合并,是否需要人工审核?
- “苹果”同时表示水果和公司时怎样消歧,是否有模型判断之外的系统化管理方式?
- 为什么采用 KB、Document、Revision、Snapshot、Artifact、Deployment 这样的分层?
- 构建失败能否断点续跑,发布后能否回滚?
- 一个知识库能否并行构建,两个任务同时到达发布节点或其中一个失败时怎样处理?
- Qdrant 和 Neo4j 为什么需要同时使用,一边写入成功、另一边失败时怎样处理,线上以哪个版本为准?
- Dense、Sparse 和 RRF 分别是什么?
- 图谱扩展为什么限制三跳而非四跳,是否有数据集评估依据?
- 两个任务怎样避免竞争更新同一个状态?
- Agent 的约束分别怎样通过程序和提示词实现,校验能覆盖哪些异常?
- 上下文压缩如何评估质量,怎样避免重复压缩?
- Agent 是否基于开源框架,怎样防止死循环和连续工具超时?
- 工具怎样分类,工具始终超时该怎样处理,跳过自有工具会有什么影响?
- 怎样优化 CLI 或 MCP 交互?工具执行要 100 秒,但 Agent 只能等待 50 秒时怎么办?
- 主节点必须拿到结果才能继续时,怎样处理长任务,是否提供心跳和进度?
- 平台的数据来自哪里,怎样保证一致性?
- 原始数据已经结构化,为什么还需要知识图谱,用 API 网关聚合能否替代图数据库?
- MySQL 与 Redis 怎样保持一致,删除缓存后如何防止大量请求冲向数据库?
- 乐观锁和悲观锁有什么区别,高并发订单更新怎样选型?
- 为什么还需要 Redis 锁,怎样设计获取与释放时机?
- 查询时数据是 A,真正修改前变成 B,应该怎样处理?
国际化广告后端,9 月 2 日
- 能否做一下自我介绍,说明电商微服务项目的性能优化措施?
- 项目中 Redis 与数据库怎样保持一致?
- 令牌桶限流怎样实现,还了解哪些限流算法?
- 分布式事务怎样实现,除 Saga 外还有哪些方案,为什么选择 Saga?
- Saga 的哪些失败会影响最终一致性,补偿操作失败时怎样处理?
后端开发,9 月 2 日
- 能否介绍个人背景和项目?
- 文档切片大小怎样确定,过大或过小分别有什么问题?
- 查询重写解决什么问题,召回流程怎样组织?
- 模型回答错误时怎样定位原因?
- 向量检索和元数据过滤怎样安排先后顺序?
- ReAct 的核心循环是什么,怎样避免无限执行并应对攻击性指令?
- 团购点评平台有哪些功能,主要业务流程是什么?
- 先更新数据库再删除缓存是否保证强一致,删除失败时怎样处理?
- 事务是什么,有哪些隔离级别?
- Redis 有哪些持久化机制,相关后台持久化为什么使用子进程而非子线程?
- 消息队列解决什么问题,如何处理重复消费、首次失败和再次执行的业务副作用?
- Java 与 Python 有什么区别,Python 是否需要编译?
《参考解析》
广告频控先确定时间窗口与误差要求
“看过就永远不展示”和“同一天最多出现若干次”需要不同的数据。先明确保留多久、是否允许误判、是否需要计数,再讨论结构。可以按活跃用户与时间窗口保存近期曝光,避免给每个注册用户永久分配一份完整广告空间。
RoaringBitmap 对不同分布采用不同容器,实际大小取决于 ID 分布和数量;不能仅凭广告总量估算压缩率。ZSet 可以用广告 ID 作为成员、曝光时间作为分数,但对象开销也要计入。需要精确次数时,还要有相应计数。上线方案应使用真实曝光分布测量内存和查询延迟。
多存储发布可以统一在版本入口切换
一个可行设计是让每次构建生成不可变版本,在两个存储里都写入该版本,校验完整后再修改线上版本指针。只完成一边的版本保持不可见,失败后可重试或清理。读请求先确定版本,再将同一版本带入两边查询。
并发发布需要比较预期旧版本和任务状态,只有获准的任务才能推进指针。回滚也是切回保留完整的旧版本。这要求存储、索引、缓存与查询都支持版本隔离;仅增加一个版本字段并不能自动获得一致性。
实体合并与检索效果要分别评估
实体名相近只能用来生成候选。还应核对类型、上下文、稳定标识与来源,低置信结果保留为待确认关系,避免错误合并污染整张图。检索侧分别测量相关材料有没有被召回、排序是否靠前,以及答案是否引用正确材料。
图谱跳数只是控制查询成本的一种参数。三跳是否足够,要看问题集上的收益与代价;不能把一次选型写成普遍规律。RRF 则按各路结果的排名融合,常见形式为各路 1 / (k + rank) 相加,不要求向量分数和关键词分数处于相同尺度。
长任务把等待状态保存下来
如果调用链只容许等待 50 秒,100 秒的工具应返回任务标识,由调用者查询状态或在完成后接收通知。Agent 的待办步骤、输入和任务标识需要持久化,恢复执行时才能接着处理结果。心跳能报告存活,但无法越过链路中的绝对执行期限。
Saga 补偿也是会失败的业务操作
每一步都记录执行结果与补偿状态,补偿操作要可重复执行,并对乱序和重复请求有明确处理方式。短暂失败可以重试;超过次数或遇到不可自动恢复的业务冲突,要进入可追踪的异常处理流程。Saga 依赖各步骤的语义补偿,不能让已经发生的外部事实自动消失。
先更新数据库再删除缓存同样不能保证强一致:并发读写和删除失败仍会产生窗口。应说明允许多长时间的旧数据、失败如何可靠重试;对严格一致的关键判断,直接使用具备事务约束的权威存储。