面灵AI→

哔哩哔哩 后端三面

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

《面试题目》

  1. 自我介绍。
  2. 为什么要做这个项目,背景和收益是什么?
  3. 流量数据采集是怎么做的?
  4. 打点是应用层面吗?
  5. 对于多个有状态服务怎么调度?
  6. 假设搜推广业务需要在各个国家/区域进行数据分析,你怎么设计?(追问:算子需要放在各个区域里面执行,还是将数据收集完由业务自己的服务执行?)
  7. AI Native 化的背景是什么?
  8. 怎么保证写操作的可靠性?
  9. 反问。

《参考解析》

流量数据采集与打点层次要分清「埋点在哪一层」这件事。按层次从低到高:① 客户端埋点(Web/App)用 SDK 上报,能拿到曝光、点击、停留时长、页面路径,难点是上报可靠性(用 navigator.sendBeacon 或批量重试队列应对页面卸载)、数据丢失和重复、以及采样策略;② 网关/接入层打点能自动拿到请求量、状态码、RT、UA、IP 归属,不需要业务改代码,但拿不到业务语义;③ 服务端应用埋点(AOP/拦截器/Middleware)能带上业务维度(用户 id、商品 id、实验分组),这是做搜推广归因最需要的一层;④ 日志/链路层(结构化日志、trace id)用于排查。所以「打点是应用层面吗」的答案是:都有,且通常是分层的——接入层做无侵入的通用指标,应用层做带业务语义的事件;两者靠同一个 trace id/请求 id 串起来。工程上必须提的几点:埋点协议要有版本号、字段变更要兼容;上报要异步+批量+本地落盘重试,不能阻塞主流程;要有实时校验(字段缺失率、量级突变的监控),否则埋点坏了几天才发现。归档到数仓一般是「客户端/服务端上报 → 接入网关(Kafka)→ 实时链路(Flink 做清洗聚合写 OLAP)与离线链路(落 HDFS/对象存储,按小时/天做 ETL)双跑」。

多个有状态服务的调度关键是承认「有状态服务不能随便漂移」这个前提。通用做法:① 把状态外置——能做成无状态的尽量做成无状态(会话放 Redis、文件放对象存储),调度器就可以用最简单的负载均衡策略;② 真正有状态的(如分片存储、有本地缓存的检索节点、消息队列的 broker)用一致性哈希或分片映射 + 调度器感知:调度时按「分片 → 节点」的映射把 pod 固定到节点(Kubernetes 里用 StatefulSet + PVC + nodeAffinity,或 StatefulSet 的稳定网络标识 pod-N.svc);③ 优雅迁移——扩缩容或故障转移时必须先摘流量、把状态刷盘或同步到新节点、再切分片所有权(类似 Redis Cluster 的 slot 迁移、Kafka 的 partition reassignment),期间要有双写或转发兜住;④ 故障域的考量——把同一分片的副本分散到不同机架/可用区,避免单点故障;⑤ 有状态服务要限制并发重启(podManagementPolicy: OrderedReady)和设置合理的 terminationGracePeriodSeconds,否则重启风暴会让数据面整体降级。答题时把「调度器要读状态拓扑、不能只看资源水位」这句说出来,是这题的核心区分点。

跨区域数据分析的算子放置是典型的「数据本地性 vs 集中计算」取舍,要分维度回答。影响决策的四个因素:数据量与传输成本(原始日志动辄 TB 级,跨区带宽贵且有出口费)、合规与数据主权(欧盟 GDPR、部分国家的数据出境限制往往直接强制本地处理,这条常常是决定性的)、延迟要求(实时看板要在区域内完成聚合,离线报表可以集中)、计算复杂度与资源(重量级模型训练通常集中在有 GPU 的区域)。常见的三种架构:① 完全下沉——每个区域部署一套完整的数据栈,在区域内做清洗和聚合,只把聚合后的指标(小体积)汇到中心;这是成本最优也最合规的做法,代价是运维复杂度乘以区域数、口径容易不一致。② 数据上收、集中计算——所有原始数据汇到中心再算;实现简单、口径统一,但跨区带宽成本和合规风险最大,只适合数据量小或区域少的场景。③ 混合/分层——区域做轻量预聚合与过滤(把维度打全、聚合到分钟级),中心做跨区域关联分析和模型训练;这是搜推广场景最常用的形态,因为归因、去重、跨区域实验对比这类计算天然需要全局视图。实际落地还要考虑:用对象存储做区域间的数据分层(Pulsar/Kafka 的 geo-replication、Iceberg/Delta 的分层存储),以及「算子下推」——把 filter/project 这类能减少数据量的操作尽量推到区域侧,把 join/全局聚合留在中心。答题收尾时给一个明确口径:「默认区域预聚合 + 中心做全局关联,除非某类分析明确要求原始粒度,否则不下传原始数据」。

写操作的可靠性从「不丢、不重、可回滚、可观测」四方面答。① 不丢:先落本地持久化(数据库事务/WAL)再返回成功,异步派生的部分用本地消息表或事务消息保证「业务成功则消息一定发出去」,配合投递重试和补偿任务兜底。② 不重:下游必须幂等,用业务唯一键 + 唯一索引、或 Redis SETNX 幂等键 + 落库记录去重,重复请求直接返回首次结果(不要只依赖 Redis,它会失效)。③ 可回滚/可恢复:关键写操作要有状态机和版本号(乐观锁 WHERE version = ?),异常时能按状态回退;对不可逆操作(支付、发券)要有对账与冲正流程。④ 可观测:写操作的 QPS、成功率、P99 时延、失败原因分布都要有指标,异常要能按 trace id 追到具体请求。另外要提「多副本一致性」:MySQL 用半同步复制或 MGR 减少主从切换丢数据,Kafka 生产端用 acks=all + min.insync.replicas>=2,Redis 关键写用 WAIT 或换 Redis 集群的强一致方案。答完补一句「先问清写操作能不能容忍重复、能容忍多大的丢失窗口」,把取舍摆在前面。

AI Native 化的背景这题通常是面试官在探你对团队方向的思考,要结合业务讲。搜推广业务的 AI Native 一般指三件事:① 把模型从「特征工程 + 排序模型」推向端到端/大模型参与,比如生成式推荐、语义召回、用 LLM 做 query 理解与素材生成;② 把研发流程本身变成 AI 驱动,例如用 Agent 做数据链路的编排、异常排查、实验配置生成,人从写代码转向定标准与审结果;③ 交互形态变化,从固定的列表页转向对话式/生成式结果,对后端意味着从「一次请求返回一页」变成「流式输出 + 工具调用 + 多轮状态管理」,对系统设计的要求是长连接、流式协议、会话状态和工具编排。回答时把它落到自己项目上:「我们的 Agent 项目就是把 X 流程从人工编排改成模型编排,收益是 Y,代价是 Z」,比空谈趋势更有说服力。