B站 AI Native 基础架构研发工程师一面:项目深挖与 Redis bitmap 追问
- 轮次
- 一面
- 时间
- 2026-09
- 来源
- 牛客网
《面试题目》
- 自我介绍
- 你挑一个你觉得最有意义的项目展开讲一下
- 先别讲技术点,从产品的角度说,这个项目在解决什么问题?
- 能不能说具体一点?比如定位一个什么问题,它整个是怎么跑的?
- 举一个具体的例子,比如线上遇到了什么问题,它怎么协助运维去解决?
- 它查监控指标是怎么查的?你说的「监控指标」具体是什么形式的东西?
- (另一个项目)你说重启之后把「正在进行」的标记为失败,又写到断线重连——这块具体是做什么的?
- 比如这个项目有几个阶段,进行到阶段四出了点问题,会怎么处理?
- 你说的那个本地文件是什么样的?主要做什么事情?主要记录什么信息?
- 你这个流程的阶段是固定死了吗?一定是 6 个吗?
- 我看你项目里写了用 Milvus 和 ES,它俩都支持向量检索,为什么要放在一起?检索流程里它们之间是怎么打配合的?
- 你这个项目是支持文档的,对线上问题,它会主动告诉你可能是什么问题吗?
- 另外两个项目有什么想讲的吗?搜索主要是在解决什么问题?
- Redis 在你这里都用到了哪些相关的知识?
- Redis 常用的数据结构有了解过吗?都有哪些?List 都能做什么操作?
- 你刚才说分片上传用 bitmap,那你这个分片会有多少个?
- 手撕:删除有序链表中重复元素 II,要求空间 O(1)、时间 O(n)
- 简历上写熟悉 Java——IoC 和 AOP 主要是干啥的?
- MySQL 索引你都了解多少?建索引有什么好处和坏处?
- ThreadLocal 能给我讲解一下吗?我用锁也可以实现隔离,为什么还要有 ThreadLocal 这个概念?
- 为什么一定要用 Redis 的 bitmap 记录分片?本地开个哈希表不行吗?或者开个数组?
- 为什么一定要引入 Redis 这么个组件来做这个事情,又或者说,你的分片是由多个服务分开传的,还是说只有一个线程在传?
《参考解析》
-
Milvus 和 ES 为什么要一起用:两者都能做向量检索,但定位不同——ES 擅长关键词倒排(BM25)和带过滤条件的结构化检索,Milvus 擅长大规模向量的近似最近邻(ANN)。典型做法是两路并行召回,再用 RRF 或加权分数做融合,最后接一个 rerank。答的时候要把「为什么要两路」说清楚:纯向量召回对专有名词、编号、精确串匹配很弱,纯关键词召回又覆盖不了语义改写,混合召回才是主流。常见追问是两路结果怎么去重、怎么定权重、候选集各取多少,这些最好能给出你项目里的真实数值。
-
分片上传为什么用 Redis 的 bitmap,而不是本地 map 或数组:核心答案是状态要跨实例共享、要能扛进程重启。本地 map 或数组只活在单个 JVM 里,服务一扩容、一重启,断点续传记录就没了,用户得从头传;Redis 的
SETBIT/GETBIT是 O(1),一位代表一个分片,1 万个分片也只占约 1.25KB,还能用BITCOUNT直接判断是否已收齐,比存一堆对象省得多。被问「只有一个线程在传吗」时,要顺势讲并发:多个上传线程甚至多个实例会同时写同一个 key,Redis 单线程执行命令天然把这类竞争串行化了,本地内存则要自己加锁、还锁不住跨实例。 -
ThreadLocal 和锁解决的不是同一个问题:锁是让多个线程在时间上排队访问同一份共享变量,ThreadLocal 是让每个线程各持一份副本、从空间上消除共享。它真正的价值在上下文透传——用户身份、traceId、事务连接这类「一路往下都要用、但层层传参太丑」的数据,放进 ThreadLocal 之后任意深度都能取。坑要说出来:线程池里线程会被复用,用完不
remove()会内存泄漏,更糟的是下一个请求读到上一个请求的残留值;InheritableThreadLocal在池化场景也不可靠,需要TransmittableThreadLocal这类方案。 -
MySQL 索引的好处与坏处要成对说:好处是减少扫描行数、把随机 IO 变成顺序 IO、顺便加速排序和连接;坏处是额外占空间、每次增删改都要维护 B+ 树(可能触发页分裂,写入变慢),索引建多了优化器还可能选错。再补一层区分度:选择性低的列(性别、状态)单独建索引基本没用,联合索引要讲最左前缀,能覆盖查询的索引可以免回表。这题答完通常接「索引失效的场景」,提前准备函数运算、隐式类型转换、
like '%x'、or连接非索引列这几条。 -
这类岗位的项目深挖怎么答:面试官一开场就要求「先别讲技术点,从产品角度说解决什么问题」,说明他考的是能不能把项目讲成一条完整链路。准备的模板是——一句话定位(给谁解决什么问题)、主流程(触发 → 处理 → 输出)、一个真实的线上案例(什么现象、怎么定位、最后什么指标变好了)、以及技术选型的理由与代价。凡是提到「监控指标」都要能说清指标名、上报方式、判定阈值,否则会被连续追问到答不上来。
-
删除有序链表中重复元素 II 的写法:哨兵节点加双指针。
pre指向最后一个确定不重复的节点,cur从dummy.next开始扫描;只要cur.val == cur.next.val,就一路跳过所有相同值的节点,然后让pre.next指向第一个不同的节点;否则pre = cur。全程只用两个指针,满足 O(1) 空间、O(n) 时间。容易踩的坑是忘记用哨兵(头节点本身可能被删)以及跳重复时循环终止条件写错。 -
IoC 与 AOP 一句话讲清再各补一层:IoC 是把对象的创建和依赖装配交给容器,业务代码只声明需要什么(构造器注入优先,字段注入不推荐);AOP 是把日志、事务、鉴权这类横切关注点从业务里抽出来,运行期靠动态代理织入。追问基本落在 JDK 动态代理和 CGLIB 的区别上:前者要求目标类实现接口、基于反射,后者靠字节码生成子类、无法代理 final 类和方法;Spring Boot 默认统一走 CGLIB。