数据来源:真实面经整理 | 版本:final
一、公司画像 & 校招节奏
哔哩哔哩(bilibili,B站)成立于,总部上海,是国内最具代表性的年轻世代内容平台。MAU超3.4亿,日均视频播放量超4亿次,员工约1万人。目前纳斯达克+港股双上市,主营业务覆盖视频、直播、游戏、电商。
B站有两个技术特点值得重点关注:第一,后端以Go为主力,C++在音视频处理方向占主导,这决定了你必须至少精通其中一门,两门都会当然更好;第二,弹幕系统是B站的技术名片,全球最复杂的实时弹幕推送技术就在B站,面试官对弹幕相关的系统设计题有天然的热情,这一块必须准备。
文化层面,B站技术团队普遍年轻,二次元氛围浓厚,面试风格比字节轻松,但技术考察深度不打折。不少同学反映B站面试官"问得很细,但不是为了为难你,更像是在讨论问题"。
主要招聘方向:
| 方向 | 代表业务 | 技术侧重 |
|---|---|---|
| 后端开发(Go为主) | 弹幕、视频、直播 | Go + 微服务,高并发 |
| 客户端(Android/iOS) | B站App | 视频播放器,Kotlin/Swift |
| 音视频工程师 | 投稿/转码/播放 | C++,FFmpeg,编解码 |
| 算法工程师 | 推荐、搜索 | Python + C++,召回 + 精排 |
| 前端开发 | Web/小程序 | Vue/React,WebAssembly |
| 数据开发 | 用户行为分析 | Flink/Spark/ClickHouse |
校招节奏(参考):
| 阶段 | 时间 | 行动建议 |
|---|---|---|
| 暑期实习转正 | 实习中做出业绩,争取转正名额 | |
| 正式网申 | jobs.bilibili.com,简历要突出Go/C++项目 | |
| 笔试 | 编程题3-4道 + 选择题(语言基础),约90- | |
| 技术面试 | 2-3轮技术面 + 1轮HR面 | |
| Offer发放 | 留意邮件,及时确认 |
备考时间建议:提前2个月开始,Go语言和弹幕系统设计至少各投入时间,这两个是B站面试的核心差异点。
二、岗位 JD 解析:技术要求拆解
B站JD写得相对简洁,但真实的考察重心从面经数据里看得很清楚。
后端开发(Go方向)
| 能力维度 | JD要求 | 真实考察重心 | 备考权重 |
|---|---|---|---|
| Go语言 | 熟悉Go语言 | GMP调度/Channel/逃逸分析/GC,每轮必问 | ⭐⭐⭐⭐⭐ |
| 高并发 | 高并发系统设计 | 百万弹幕并发场景,结合业务考 | ⭐⭐⭐⭐⭐ |
| 弹幕/直播 | 了解实时系统 | 弹幕推送完整方案,B站特色题 | ⭐⭐⭐⭐⭐ |
| 数据库 | MySQL/Redis | ZSet排行榜、HyperLogLog UV统计 | ⭐⭐⭐⭐ |
| 消息队列 | 了解MQ | Kafka在弹幕异步处理中的应用 | ⭐⭐⭐⭐ |
| 算法 | 数据结构与算法 | Medium题为主,链表+LRU高频 | ⭐⭐⭐⭐ |
音视频工程师(C++方向)
| 能力维度 | JD要求 | 真实考察重心 | 备考权重 |
|---|---|---|---|
| C++语言 | 精通C++ | 智能指针原理,手写实现 | ⭐⭐⭐⭐⭐ |
| 编解码 | 音视频基础 | H.264/H.265/AV1,I/P/B帧原理 | ⭐⭐⭐⭐⭐ |
| FFmpeg | 了解FFmpeg | 转码流程,命令行使用 | ⭐⭐⭐⭐ |
| 网络传输 | 流媒体协议 | HLS vs DASH vs RTMP的场景选择 | ⭐⭐⭐⭐ |
| 内存管理 | C++内存管理 | RAII,智能指针,手写shared_ptr | ⭐⭐⭐⭐⭐ |
核心差异点:B站面试与其他大厂的不同
两个考点在B站出现频率明显高于其他公司:
Go逃逸分析:其他大厂很少深问,B站几乎每轮都会问。逃逸分析影响性能,B站后端性能要求高,所以这是刚需知识,不是选考内容。
弹幕系统设计:这是B站面试的"必做题"。不是"可能考",是"一定考"。弹幕推送、弹幕存储、弹幕过滤、弹幕同步,这四个方向都要准备。
三、LeetCode 高频题 Top 20(真实面经数据)
B站算法题整体难度:Medium为主,Hard出现概率低于字节,但Medium要做到熟练。Go和C++方向侧重点有差异——Go方向侧重系统设计+基础算法;C++方向会要求手写数据结构(比如自己实现shared_ptr)。
第一梯队:必刷(每道至少做3遍)
| 排名 | 题目 | 题号 | 出现频率 | 考察方向 | B站特色备注 |
|---|---|---|---|---|---|
| 1 | 反转链表 | No.206 | ⭐⭐⭐⭐⭐ | Go/C++均考 | 入场券,不会直接淘汰 |
| 2 | LRU缓存机制 | No.146 | ⭐⭐⭐⭐⭐ | 高频,与弹幕缓存结合 | 会追问"弹幕池怎么用LRU设计" |
| 3 | 二叉树层序遍历 | No.102 | ⭐⭐⭐⭐ | 各种变形 | 考变形题:按层输出/锯齿形 |
| 4 | 无重复字符最长子串 | No.3 | ⭐⭐⭐⭐ | 滑动窗口基础 | 有时结合字符串处理场景 |
| 5 | 合并K个排序链表 | No.23 | ⭐⭐⭐⭐ | 中高频 | 考堆的使用,C++方向必刷 |
第二梯队:高频(至少做2遍)
| 排名 | 题目 | 题号 | 出现频率 | 考察方向 |
|---|---|---|---|---|
| 6 | 数组中的第K个最大元素 | No.215 | ⭐⭐⭐⭐ | 堆/快选 |
| 7 | 三数之和 | No.15 | ⭐⭐⭐⭐ | 双指针 |
| 8 | 合并两个有序链表 | No.21 | ⭐⭐⭐⭐ | 链表基础 |
| 9 | 环形链表 | No.141 | ⭐⭐⭐⭐ | 快慢指针 |
| 10 | 二叉树的最近公共祖先 | No.236 | ⭐⭐⭐ | DFS递归 |
| 11 | 合并两个有序数组 | No.88 | ⭐⭐⭐ | 双指针 |
| 12 | K个一组翻转链表 | No.25 | ⭐⭐⭐ | 链表进阶 |
| 13 | 合并区间 | No.56 | ⭐⭐⭐ | 排序+贪心 |
| 14 | 接雨水 | No.42 | ⭐⭐⭐ | 双指针/单调栈 |
| 15 | 重排链表 | No.143 | ⭐⭐⭐ | 链表综合 |
第三梯队:中频(至少做1遍)
| 排名 | 题目 | 题号 | 出现频率 | 考察方向 |
|---|---|---|---|---|
| 16 | 岛屿数量 | No.200 | ⭐⭐⭐ | BFS/DFS |
| 17 | 全排列 | No.46 | ⭐⭐ | 回溯 |
| 18 | 最长回文子串 | No.5 | ⭐⭐ | 动态规划/中心扩展 |
| 19 | 滑动窗口最大值 | No.239 | ⭐⭐ | 单调队列 |
| 20 | 编辑距离 | No.72 | ⭐⭐ | DP进阶 |
刷题规律总结
规律1:链表题是基本盘。反转、合并、环检测、K组翻转,这些链表题出现频率很高,Go和C++两个方向都要刷透。
规律2:LRU要和弹幕场景结合理解。单纯刷LRU不够,面试官会问:"B站弹幕池怎么设计?弹幕量超大怎么分层?" 要能把LRU和实际业务场景接通。
规律3:Hard题不是重点。B站很少出Hard题,Medium刷到熟练远比硬磕Hard题有价值。时间有限的话,第一梯队5题 + 第二梯队10题,优先级高于第三梯队。
规律4:音视频岗有数据流相关题目。如果投音视频工程师,偶尔会考数据流处理相关的题目,比如求数据流中的中位数(No.295),要额外注意。
四、技术面试考点
Go语言专项(后端核心)⭐⭐⭐⭐⭐
GMP调度模型(每轮必问):
- G(Goroutine):用户态轻量级线程,初始栈2KB,可增长
- M(Machine):内核线程,M:N模型中的N端
- P(Processor):逻辑处理器,数量由GOMAXPROCS决定,绑定G队列
- 调度时机:channel阻塞、syscall、主动yield(runtime.Gosched())
面试官最爱追问:"P的本地队列满了怎么办?"(答:放入全局队列,其他P可以偷取——work stealing机制)
Channel机制(高频考点): - 向已关闭的channel发送数据 → panic - 从已关闭的channel读取数据 → 返回零值,ok为false - 无缓冲channel:发送和接收必须同时就绪(同步) - 有缓冲channel:缓冲区满时发送阻塞,缓冲区空时接收阻塞
逃逸分析(B站特色高频考点):
这个考点在B站出现频率明显高于其他大厂,因为B站后端对性能要求高,逃逸分析直接影响GC压力。
三种典型逃逸场景:
1. 接口赋值:var i interface{} = x,x会逃逸到堆
2. 返回局部变量指针:函数返回指向局部变量的指针,该变量逃逸
3. slice动态扩容超过栈限制:大对象直接在堆上分配
如何分析逃逸:
go build -gcflags="-m" main.go
输出中有escapes to heap就是逃逸了。
逃逸的影响:堆上分配需要GC介入,压力大;栈上分配自动回收,性能更好。优化手段:使用sync.Pool复用对象,减少堆分配频率。
面试官高频追问:"你在项目里有没有用逃逸分析优化过性能?"——要有一个具体案例。
GC相关:
- Go使用三色标记+写屏障的并发GC
- 减少GC压力的方法:减少内存分配次数、使用sync.Pool复用、避免大量小对象
切片底层:
- 切片是{ptr, len, cap}三元组
- 多个切片共享底层数组时的修改问题(append可能触发扩容,导致底层数组不再共享)
C++专项(音视频/客户端方向)⭐⭐⭐⭐⭐
智能指针原理(B站特色考点):
B站C++方向对智能指针的考察深度,在国内大厂中属于顶级水平。仅仅知道"unique_ptr独占,shared_ptr共享"是不够的,要能解释底层原理。
unique_ptr: - 独占所有权,不可复制,只可移动(move语义) - 析构时自动释放资源,零开销抽象(和裸指针性能一样)
shared_ptr:
- 引用计数机制(内部用原子操作保证线程安全)
- 底层有两个指针:一个指向对象,一个指向控制块(control block)
- 控制块存储:引用计数、弱引用计数、删除器
- make_shared<T>()只分配一次内存(对象+控制块合并),比shared_ptr<T>(new T())更高效
weak_ptr:
- 不增加引用计数,不拥有对象所有权
- 通过lock()获取shared_ptr,如果对象已释放则返回空
- 核心作用:打破循环引用
循环引用经典场景(面试必考):
struct A { shared_ptr<B> b; };
struct B { shared_ptr<A> a; };
// A引用B,B引用A → 引用计数永远不为0 → 内存泄漏
// 解决:把其中一个改为weak_ptr
struct B { weak_ptr<A> a; }; // 不增加引用计数,打破循环
面试官高频追问链: - "shared_ptr线程安全吗?"(答:引用计数操作是线程安全的,但同时读写同一个shared_ptr对象不是线程安全的) - "为什么用weak_ptr能解决循环引用?"(答:weak_ptr不增加引用计数,A的引用计数可以降为0,触发析构)
右值引用与move语义:
- std::move:将左值转换为右值引用,不做实际移动,只是类型转换
- 移动构造函数:接管资源所有权,被移动对象置于有效但未指定状态
- 完美转发:std::forward<T>(arg),保持参数的值类别
虚函数与vtable: - 每个含虚函数的类有一个vtable(虚函数表),存放函数指针 - 每个对象有一个vptr(虚指针),指向所在类的vtable - 多继承时有多个vptr,vtable布局更复杂
弹幕系统设计(B站独特考点)⭐⭐⭐⭐⭐
这是B站面试中最有特色的考点,其他公司不会考,但B站几乎必考。完整的弹幕系统方案要从四个维度准备:
维度1:实时弹幕推送 - 用户发弹幕 → 后端接收 → 广播给同一视频的所有在线用户 - 技术选型:WebSocket长连接(比HTTP轮询延迟低、服务器压力小) - 消息广播:同一视频的用户订阅同一个Topic,通过Kafka解耦发送和接收 - 分组策略:按视频ID分组,避免全局广播
维度2:弹幕存储 - 热数据:Redis缓存最近N条弹幕(N = 100~500,按视频播放时间轴存储) - 冷数据:MySQL或Cassandra持久化(Cassandra写入性能更好,适合大量弹幕写入) - 存储设计:以视频ID + 时间戳为主键,支持按时间范围快速查询
维度3:弹幕过滤 - 关键词过滤:DFA算法(确定性有限自动机),构建敏感词树,O(n)时间复杂度 - AI审核:对疑似违规弹幕进入AI审核队列,异步处理 - 用户维度:屏蔽特定用户、屏蔽自定义关键词
维度4:弹幕同步(视频暂停/快进) - 弹幕绑定视频时间轴(PTS,Presentation Timestamp),不是绝对时间 - 用户快进到180s → 拉取180s附近的弹幕缓存 - 暂停 → 停止新弹幕推送,恢复播放 → 重新订阅当前PTS的弹幕流
百万并发弹幕的处理: - 垂直拆分:按视频ID分片,热门视频单独部署WebSocket服务节点 - 水平扩展:无状态的WebSocket服务,通过一致性哈希路由 - 消峰:Kafka作为缓冲层,消费端异步写入存储
高频追问:"弹幕的实时性和一致性如何平衡?"(答:弹幕不需要强一致性,最终一致性即可。优先保证实时性,允许极小概率的弹幕乱序或短暂延迟)
数据库专项(通用方向)⭐⭐⭐⭐
Redis高级数据结构(B站常考):
- ZSet实现热门视频排行榜:ZADD rank 播放量 视频ID,ZREVRANGE rank 0 9取Top10
- HyperLogLog统计视频UV:PFADD uv_视频ID 用户ID,PFCOUNT uv_视频ID
- 为什么用HyperLogLog?误差率约0.81%,内存只需12KB,而Set存储千万UV需要几百MB
- Bitmap统计用户签到:每个bit代表一天,一年只需46字节
MySQL分库分表: - 视频稿件表按uid分库(根据用户ID取模) - 弹幕表按视频ID分表(同一视频的弹幕在同一分片) - 跨分片查询问题:避免跨库JOIN,用业务层聚合
Kafka在弹幕场景的应用: - Topic:一个视频对应一个或多个Partition - 弹幕写入:生产者发布弹幕消息 → 消费者异步写入存储 → 广播给在线用户 - 保证顺序:同一视频的弹幕发到同一Partition,单Partition内消息有序
音视频基础(音视频岗)⭐⭐⭐⭐⭐
编解码基础: - H.264/AVC:最广泛支持,压缩效率均衡,硬件解码支持好 - H.265/HEVC:同质量比H.264节省约50%带宽,但编码复杂度更高 - AV1:开源免版税,压缩效率优于H.265,B站正在推进AV1转码 - I/P/B帧:I帧完整关键帧(最大)、P帧参考前帧(中)、B帧双向参考(最小)
流媒体协议选择: - RTMP:低延迟(约1-3秒),适合直播推流,但需Flash支持(已淘汰) - HLS:延迟高(10-30秒),基于HTTP分片,兼容性好,适合点播 - DASH:类似HLS,支持ABR(自适应码率),Netflix主推 - WebRTC:超低延迟(<500ms),适合连麦等实时场景
低延迟直播优化: - 减小切片时长(HLS从10s降到2s) - 使用CMAF格式提升兼容性 - CDN边缘节点就近加速
五、面经规律总结
面试风格画像
B站面试有一个明显特点:技术深度 + 业务场景结合。面试官不会单纯考"手写快排",而是会把算法题和业务场景接起来——"你实现了LRU,那B站弹幕池怎么设计?"这种追问方式在B站很典型。
面试氛围相对轻松,面试官普遍年轻(很多是应届生带届生),喜欢技术讨论而不是考试式审问。但不要误判——轻松的氛围不等于低要求,追问会追到底层原理。
高概率追问链
智能指针追问链(C++方向几乎必问):
shared_ptr是什么?
→ 追问:引用计数是如何实现线程安全的?(原子操作)
→ 追问:循环引用具体怎么发生?(A→B→A,引用计数永远≥1)
→ 追问:weak_ptr为什么不增加引用计数?(只记录弱引用计数,不阻止对象析构)
→ 追问:能手写一个简化版shared_ptr吗?(控制块+引用计数+析构逻辑)
Go逃逸追问链(Go方向高频):
什么是逃逸分析?
→ 追问:举3个会逃逸的典型场景?
→ 追问:怎么查看代码里哪些变量逃逸了?(go build -gcflags="-m")
→ 追问:逃逸对性能有什么影响?如何优化?(sync.Pool,减少堆分配)
→ 追问:你项目里有没有因为逃逸问题导致的性能问题?怎么排查的?
弹幕系统追问链(每家公司都会问的设计题,B站会追得更深):
弹幕系统怎么设计?
→ 追问:百万并发弹幕怎么处理?(分片+WebSocket集群+Kafka消峰)
→ 追问:弹幕的实时性和一致性如何平衡?(最终一致性,优先实时性)
→ 追问:用户快进时怎么加载弹幕?(按PTS时间轴拉取缓存)
→ 追问:弹幕存储怎么设计分层?(Redis热数据 + Cassandra冷数据)
LRU + 业务追问链:
手写LRU
→ 追问:B站弹幕池怎么用LRU设计?(LRU淘汰冷弹幕,保留热弹幕段)
→ 追问:如果弹幕量超大,单个LRU扛不住怎么办?(分片LRU,按视频ID分片)
→ 追问:LRU的时间复杂度是多少?能优化吗?(O(1),哈希表+双向链表)
笔试特点
- 题型:编程题3-4道 + 选择题(Go/C++基础知识,音视频岗有音视频相关选择题)
- 难度:编程题Medium为主,Hard偶尔出现
- 时间:90-
- 特点:Go语言基础选择题可能考channel、goroutine、接口等,C++方向可能考指针、虚函数等
- 策略:先把编程题全做完,选择题利用剩余时间完成,不确定的题目猜默认最直观的答案
不同岗位的差异
| 岗位 | 算法题权重 | 系统设计权重 | 语言专项权重 | 备注 |
|---|---|---|---|---|
| 后端(Go) | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐(Go专项) | 弹幕设计必考 |
| 音视频(C++) | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐(C++专项+音视频) | 编解码必考 |
| 算法工程师 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐(Python为主) | 推荐系统必考 |
| 客户端(Android/iOS) | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐⭐(Kotlin/Swift) | 视频播放器优化考察 |
| 前端 | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐(JS/TS+Vue) | WebAssembly了解加分 |
校招节奏
整体策略
B站备考有一个核心原则:Go/C++语言专项和弹幕系统设计要早投入,不能靠临时抱佛脚。这两个方向的考察深度决定了你必须有深度理解,而不是表面背诵。
如果只有,优先级排序是:语言专项(Go或C++)> 弹幕系统设计 > 算法题(链表+LRU) > 数据库 > 其他。
详细计划
| 阶段 | 时间 | 重点任务 | 每日用时 |
|---|---|---|---|
| Phase 1:C++智能指针 | unique_ptr/shared_ptr/weak_ptr原理;手写简化版shared_ptr(含引用计数);循环引用问题画图演示 | 2- | |
| Phase 2:Go语言专项 | GMP调度模型;Channel各种情况;逃逸分析3种场景+查看工具;GC机制;sync.Pool使用 | 2- | |
| Phase 3:数据库+Redis | ZSet排行榜设计;HyperLogLog UV统计原理和适用场景;MySQL分库分表策略;Kafka基础 | ||
| Phase 4:弹幕系统设计 | 实时推送(WebSocket+Kafka);存储分层(Redis+Cassandra);过滤方案;快进时弹幕同步;百万并发处理 | ||
| Phase 5:算法专项 | LRU手写(Go+C++两个版本);链表全系列(反转/合并/环/K组翻转);滑动窗口;堆应用 | ||
| Phase 6:冲刺 | 音视频基础补充(针对音视频岗);看最新B站面经;整理项目中弹幕/视频相关点;模拟面试 |
最低备考标准(上场前必须达到)
- [ ] 智能指针循环引用问题能画图演示(A→B→A的引用计数问题,以及weak_ptr如何打破)
- [ ] Go逃逸分析能举出3种典型逃逸场景,知道如何用命令查看
- [ ] 弹幕实时推送完整方案能讲清楚(WebSocket + Kafka + Redis热存储 + 冷存储三层架构)
- [ ] LRU缓存能在内手写(Go或C++均可,HashMap + 双向链表)
- [ ] HyperLogLog用于视频UV统计的理由能解释(误差率约0.81%可接受,内存从几百MB降到12KB)
- [ ] 至少熟练掌握第一梯队5道题,能在内写出clean code
各岗位备考调整
投后端(Go方向):Phase 2 Go语言专项延长到(),弹幕系统设计是重中之重,不可压缩。
投音视频(C++方向):Phase 1 C++专项延长到(),Phase 6 冲刺时重点补充H.264/H.265/FFmpeg知识,能说清楚转码流程。
投算法工程师:Phase 5 算法专项延长到(),增加推荐系统基础:召回+排序的基本架构,CTR预估的常见模型。
一句话建议
B站面试最大的坑是只刷题不准备弹幕系统设计,然后被追问得哑口无言。弹幕设计不是加分题,是必答题。里,至少花时间把弹幕系统的完整方案推演3遍,每遍都从"用户点击发送"到"其他用户看到弹幕"全链路走一遍,直到能流畅讲出来为止。