去年秋招季很多学弟学妹问我B站后端开发方向笔试到底考什么。说实话B站这几年校招笔试的题目风格变化不小2023届的笔试卷A更偏向“基础工程”的组合而不是纯粹刷LeetCode。如果你只刷题不补基础很容易在选择题上翻车如果你只背八股不写代码编程题又会暴露真实水平。我花了几个晚上把这套卷子的考点和答题思路重新捋了一遍写下这篇复盘希望能给准备后端开发岗的同学一些参考。这套卷子整体分为三个部分客观选择题、编程题和简答设计题。考察范围覆盖计算机网络、操作系统、数据库、Java/Go语言基础、并发编程、算法与数据结构以及一道典型的系统设计题。接下来我按题型拆解把高频考点、典型陷阱和实战经验都讲清楚。1. 这套卷子的题型分布选择题、编程题、设计题各占多少1.1 整体题型与分值占比先说结论整套卷子满分100分客观题占了40分左右编程题30分设计题20分剩下10分是一些简单问答和逻辑推理。这个分值结构意味着就算你编程题全部AC客观题考砸了也一样挂。我根据印象整理了一份题型分布表帮助大家直观感受题型题量单题分值考察重点单选/多选20题2分网络、OS、数据库、语言基础、并发编程题2题15分/题算法与数据结构、代码完整性简答设计题1题20分系统设计、方案权衡、工程思维逻辑/数学题5题2分概率、排列组合、推理从分值能看出B站并不想招一个只会背答案的人。客观题考的是你大学四年有没有认真上课编程题考的是有没有刷题手感设计题考的则是能不能把知识串起来解决实际问题。这套组合下来能比较真实地反映一个候选人的计算机基础扎实程度。1.2 为什么B站会把设计题放进笔试很多公司笔试只做选择题和算法题B站却很早就开始在设计题上做文章。原因在于后端开发岗位日常工作离不开系统设计。比如一个视频播放量统计看起来简单但真正设计时要考虑数据量大不大、要不要实时、缓存和DB怎么同步、排行榜怎么更新。这些问题用笔试来筛选比面试时临时问更高效也能刷掉一批“只会写CRUD”的简历选手。设计题通常给一个业务场景让你写接口定义、数据表结构、缓存方案、或者画出架构流程。难倒很多人的不是不会写代码而是不知道从何处下手。我后面单独用一个章节讲这套卷子的设计题思路。2. 选择题高频坑网络、数据库与并发编程的典型陷阱2.1 TCP三次握手和四次挥手考的不是背是细节这道题几乎每年笔试都有但大部分人只背了“三次握手四次挥手”的流程考试时以为稳了结果栽在细节上。我记得卷子里有一道多选问“关于TCP四次挥手下列描述正确的是”。选项里有几个特别容易混淆的服务器收到FIN后先进入CLOSE_WAIT状态再继续发送未发送完的数据。主动关闭方进入TIME_WAIT状态后需要等待2MSL才能关闭。如果服务器同时收到FIN和ACK可以合并为三次挥手。四次挥手一定是客户端先发起。第四个选项错得很经典因为四次挥手的发起方不一定是客户端任何一端都可以主动关闭。第三个也是对的如果通信双方同时关闭或者服务端在收到FIN后没有数据要发了ACK和FIN可以合并发送这就是“三次挥手”的由来。这个考点本身不难难在平时只记流程不思考原因。比如TIME_WAIT为什么是2MSL因为要保证最后一个ACK能到达对方如果丢了对端会重发FIN2MSL足够一个报文最大生命周期内重发一次。知道这个底层原因很多干扰选项一眼就能看穿。2.2 数据库索引失效B树之外的判断逻辑数据库也是重头戏。题目会给你一条SQL问它能不能命中某个联合索引(user_id, create_time, status)。比如where user_id 1 and status 2能用到部分索引但只有user_id能走索引status不行因为联合索引最左前缀原则跳过了create_timestatus无法使用索引。where create_time 2023-01-01 and user_id 1在MySQL优化器有优化的情况下可能调整顺序但笔试默认按联合索引定义顺序判断所以只能命中user_id。where status 2彻底失效因为没有从最左列开始。还有一道题考select * from table where user_id like %123这种左模糊查询会导致索引失效因为B树无法根据前缀匹配定位。很多人会误以为加个索引就万事大吉实际上索引的参与条件和列的顺序、查询条件、数据分布都强相关。我的建议是复习时不要只背“最左前缀”“不要用函数”这些口诀要理解B树的查找过程索引是一棵排序树查询只能从最左列开始逐列比较如果跳过或者对列做了计算排序信息就丢失了。理解了这一点索引失效的题目就是送分题。2.3 并发编程从锁到内存可见性卷子里有一道关于Java并发经典的题目问volatile能保证什么。选项有原子性、可见性、有序性、持久性。很多人知道volatile能保证可见性和有序性但不能保证原子性。这就是坑。volatile解决的是内存可见性和指令重排序问题它不会对count这种复合操作做任何原子性保护。所以多线程环境下用volatile做计数器结果必错。考场上经常会把volatile和synchronized放在一起考要记住volatile不是锁它无法保证多个线程互斥。还有一道问ThreadLocal的原理选项里说“ThreadLocal是存在Thread里面的一个Map”这个描述不完全对但选“每个线程有自己的副本”就对了。ThreadLocal本质上是在每个Thread对象里维护一个ThreadLocalMap所以线程隔离。但要注意内存泄漏问题ThreadLocalMap的key是弱引用value是强引用如果线程池复用线程value可能一直无法回收。笔试可能不会考这么深但面试会问。如果是Go方向的同学B站也有Go后端的卷子重点会放到goroutine、channel、sync.Mutex和原子操作上。核心思路是一样的并发问题的本质是共享可变状态的管理搞清楚锁、信号、内存模型的边界就够了。3. 编程题实战一道“最长无重复子串”的完整解题过程编程题一共两道分值不低。第一道是比较经典的滑动窗口题第二道是自拟结构的设计题。这里我用一道示例题来复盘这类题目的满分写法题目是“给定一个字符串找出其中不含有重复字符的最长子串长度”。3.1 题目描述与输入输出约定输入一个字符串例如abcabcbb输出最长无重复子串的长度。对于abcabcbb最长无重复子串是abc长度3。约定字符串只包含英文字母、数字、符号和空格长度范围0到50000。要求时间复杂度O(n)空间复杂度O(min(m,n))其中m是字符集大小。如果你只写了暴力解法能过一部分用例但数据量大的case会超时。笔试题要求的是能跑完所有测试点。3.2 暴力解与问题分析暴力解很简单枚举左边界i和右边界j用Set判断区间内是否有重复字符。复杂度O(n^2)对于长度5万的字符串完全不可行。所以关键思路是如何在向右滑动右指针时快速判断左指针该移动到什么位置。3.3 滑动窗口优化及Java实现滑动窗口的思路是用左右两个指针维护一个不重复窗口。右指针每次向右移动一个字符如果遇到重复字符就不断收缩左指针直到窗口内没有重复。这样每个字符最多被访问两次时间复杂度O(n)。但笔试时要求代码整洁直接使用HashMap记录每个字符最后出现的位置左指针跳转更快。逻辑如下初始化一个HashMap记录字符到它最后一次出现的位置的下一个位置也就是窗口的左边界候选。遍历字符串设当前位置i的字符为c。如果map里已经有c则将左边界left更新为max(left, map.get(c))确保窗口内没有重复。把c和下一个位置i1存入map更新答案ans为max(ans, i-left1)。Java代码import java.util.HashMap; public class LongestSubstringWithoutRepeating { public int lengthOfLongestSubstring(String s) { HashMapCharacter, Integer lastPos new HashMap(); int left 0; int ans 0; for (int i 0; i s.length(); i) { char c s.charAt(i); if (lastPos.containsKey(c)) { left Math.max(left, lastPos.get(c)); } lastPos.put(c, i 1); ans Math.max(ans, i - left 1); } return ans; } }这段代码的关键是lastPos.get(c)存储的是“下一个位置”而不是当前下标这样遇到重复字符时左边界可以一次性跳到重复字符之后不需要一步一步收缩。代码简洁也避免了Set动态删除的繁琐。3.4 笔试现场的边界条件处理这道题最容易错的不是主逻辑而是边界空字符串输入长度为0循环不会执行返回0不会错。字符串里全是相同字符比如bbbbbb每次遇到重复left直接跳到当前字符的下一个位置ans始终为1。字符串里全是不同字符比如abcdeflastPos每个都不重复ans最终等于全串长度。字符包含空格的比如ab c abc空格也算一个字符charAt可以直接处理。另外笔试平台可能要求自己写输入输出。题目里给了String参数部分平台还要求读标准输入。如果你用Scanner读整行注意next和nextLine的区别别因为读取方式不对导致空字符串无法测试。这道题在LeetCode上叫“无重复字符的最长子串”属于热门题。但考场上的关键是快速写出正确且整洁的代码然后抽几分钟跑一下边界case。如果你能一次性通过所有提交编程题这部分就稳了。4. 设计题该怎么写以“视频热门榜”为例的答题框架设计题是B站笔试的特色这道题很考验工程能力。卷子里的设计题场景是“设计一个视频热门榜”要求每天展示点击量TOP100的视频支持小时级更新。题目没有给出明确的用户量和数据规模所以答题的第一步是做合理的假设。4.1 先做需求边界和量级估算别急着画架构图很多人看到设计题上来就画Nginx、Redis、MQ、数据库四件套这是大忌。评分标准首先看你的需求分析是否到位如果没有估算方案就没有依据。我当时是这么写的假设B站日活用户1亿每天产生100亿次播放行为。视频总量1亿条热门榜只取前100。按小时更新也就是每小时需要从新增播放记录里汇总一次生成新的榜单。这个规模说明如果每次实时扫描全量视频根本吃不住。所以必须采用离线计算结果缓存的方式。比如每小时跑一次定时任务读取过去1小时的所有播放事件合并到当天的累计播放次数里然后计算Top100写入Redis缓存。用户请求热门榜时直接读缓存不查数据库。4.2 接口与数据模型设计接口设计不是写RESTful CRUD而是要体现业务含义。我写的接口是GET /api/hot-list?date2023-09-01typeall返回某天热门视频列表。响应字段包括video_id, rank, score, play_count。数据表方面我设计了video_play_count表字段video_idbigintdatedatehourintplay_countbigint主键是(video_id, date, hour)这样每天每小时一行记录。最终榜单的score可以定义为播放量点赞量加权的得分权重不同视频的热度值也不同。4.3 缓存、异步与降级方案热门榜列表写入Redis的zsetkey是hot_rank:{date}member是video_idscore是热度值。用户请求直接ZREVRANGE hot_rank:2023-09-01 0 99。这样既支持排序又支持分页。异步方面播放事件通过消息队列传递比如Kafka。服务端收到播放请求后写入MQ由消费者异步累加到对应小时bucket里不影响主流程。这样即使高峰期播放量暴增核心接口也能稳定。降级方案也不能少。如果Redis挂了接口可以回退到MySQL查预计算好的榜单表虽然性能差点但不会直接报错。如果MySQL也挂了就返回HTTP 503同时告警。这些细节在笔试里能明显拉开差距。4.4 笔试评分到底看什么据我后来和参与过校招的朋友交流设计题评分主要看四件事是否做量级估算、是否设计合理的数据存储、是否有缓存和异步思想、是否提到容灾降级。能把四件事说清楚就算方案不是最优依然能拿高分。最重要的是不要写成“用户点击MySQL查询”的小作业要让人感受到你有系统设计意识。B站业务体量很大笔试考察的就是你有没有“大流量下依然稳定”的概念。5. 我在笔试现场的三个教训时间分配、输入格式与心态5.1 时间分配方案40-30-20-10B站这套卷子一般给90分钟。我最开始准备写选择编程设计但实际容易纠结选择题导致后面紧张。复盘后我总结的时间分配是前10分钟快速浏览全部题目标记出会做和不会做的题。客观题最多用40分钟遇到卡壳超过2分钟的先跳过。编程题用30分钟每题最多15分钟如果15分钟没有完整思路先写暴力解法保底。最后10分钟处理设计题或检查已答内容。设计题虽然分值20分但如果编程题没完成损失更大。合理取舍很关键。5.2 输入输出处理本地明明AC线上全错我遇到过最惨的现场事故编程题在IDE里跑得好好的提交到笔试平台却0分。后来发现是输入输出格式错了。很多笔试平台要求从标准输入读取用Scanner读取时如果题目有多行输入不能只用一个nextInt要循环读取。我给你一个通用做法在本地写题时一定要先看题目给的示例输入是不是包含多行然后写一个完整读取的模板。比如import java.util.*; public class Main { public static void main(String[] args) { Scanner sc new Scanner(System.in); String line sc.nextLine(); // 如果有多行用 while (sc.hasNextLine()) 循环读 System.out.println(lengthOfLongestSubstring(line)); } }注意如果一行可能有空格要用nextLine()而不是next()。如果读数字用nextInt()读下一行时注意换行符残留。这个小细节经常把人搞崩。5.3 不会的题先跳但别留空白选择题不会可以先用排除法蒙一个空着跟蒙一个都可能错但蒙一个好歹有四分之一概率。编程题如果没思路把输入输出框架和暴力解写上也能拿部分分。设计题哪怕只有思路没细节写下关键点和流程也能让阅卷人看到你的分析过程。最怕的是心态崩了从头到尾死磕一道难题最后简单题也没时间做。校招笔试不是竞赛没有“解出难题才算赢”的说法把该拿的分拿满就够了。5.4 选择题不确定时怎么蒙多选选择题如果怕错选扣分可以采取保守策略不确定的选项不选。单选的话排除两个明显错误后在剩余两个里按第一直觉选择不要反复改。我做过测试第一直觉的正确率往往高于反复修改后的答案。6. 笔试后的查漏补缺后端校招核心知识点对照清单题目做完不是结束真正的成长来自对照知识点清单查漏补缺。我每次笔试完都会整理一份“哪里不会补哪里”的表格这也是我能从秋招小白到收获Offer的关键方法。6.1 知识点清单表格分类核心知识点校招常见考法数据结构数组、链表、栈、队列、哈希、二叉树、堆算法题直接考察选择题考复杂度分析算法二分、双指针、滑动窗口、DFS/BFS、动态规划、贪心编程题高频需达到手写无bug计算机网络TCP/UDP、HTTP/HTTPS、DNS、TCP拥塞控制、常见状态码选择题、简答题操作系统进程/线程、调度算法、死锁、虚拟内存、IO多路复用选择题面试常问数据库索引、事务隔离级别、MVCC、锁、SQL优化选择题、设计题Java基础集合源码、异常、泛型、反射、JVM内存模型、垃圾回收选择题、面试并发编程synchronized、volatile、AQS、线程池、CAS选择题、设计题分布式基础Redis、消息队列、分布式锁、一致性哈希、幂等设计题核心系统设计量级估算、接口设计、存储选型、缓存策略、降级限流设计题Linux文件系统、常用命令、进程查看部分选择题会涉及6.2 优先级与复习路线建议如果你是现在才开始准备我的建议是算法题每天保持2-3道不要贪多但一定要把每道题的最优解想清楚尤其是“为什么这样写”以及“能不能再优化”。计算机网络和数据库放在第二优先级因为面试和笔试都会遇到。重点看TCP状态转换、HTTP缓存机制、索引底层的B树、事务隔离级别。并发编程和JVM是拉开差距的点但分值不一定高。可以放到笔试前一周集中刷。系统设计不需要看太多理论把“秒杀系统”“短链系统”“排行榜系统”三四个经典案例吃透学会套模板即可。每场笔试后一定要复盘。我最开始因为懒考完就丢结果下次遇到类似考点还是错。后来逼着自己做知识图谱把薄弱点标红下一次复习先看红点。这套B站2023校招笔试卷A难度整体中等偏上不是那种纯刷题就能过的卷子。它要求你对计算机基础有系统性的理解同时具备解决真实工程问题的思维。如果你能把这份清单里的知识点按优先级过一遍再做两三套模拟题相信你也能在笔试中稳定发挥。最后再分享一个小技巧笔试前把可能会用到的模板代码提前准备好比如滑动窗口模板、TopK模板、链表反转模板、树的遍历模板但务必自己敲一遍再背。这样遇到类似题目能省下大把推导时间把精力留给真正需要思考的部分。祝大家都能拿到心仪的Offer。