ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

B站2019秋招技术岗笔试题复盘:四个方向的考点与解法

B站2019秋招技术岗笔试题复盘:四个方向的考点与解法 这套题我印象挺深的B站2019秋招技术岗第二套笔试题当时做完第一感觉就是B站是真的想把“会写业务代码的人”和“能解决实际问题的人”区分开。四个方向——前端、运维、后端、移动端——看似各自独立但题目里埋的线全是视频网站的核心场景高并发、弹幕推送、播放体验、资源调度。这篇文章我会按岗位方向挨个复盘把题目背后的考点、命题意图、我当时的答题思路以及后来工作里验证过的正确解法都串一遍。如果你正在准备大厂技术岗笔试或者已经在做相关方向想补一补底层认知这篇应该能帮你少走不少弯路。1. 这套题到底在考什么先看整体格局1.1 四个岗位共用一套题的隐藏逻辑B站这套笔试题不是简单的“前端做前端的题、后端做后端的题”它更像是一次全链路技术素养摸底。前端题里藏着网络协议后端题里闪着缓存一致性运维题绕不开Linux内核参数移动端题又跟服务端接口设计挂钩。这套卷子的潜台词是你不仅要懂自己那一亩三分地还得知道上下游是怎么协作的。拿视频播放这条链路举例用户在App点开一个视频移动端要发起请求、前端要渲染页面、后端要返回推荐列表和播放地址、运维要保证CDN节点和网关稳定。任何一环出问题用户感知就是“卡了”“打不开”“加载慢”。所以这套题把四个方向揉在一起考本质上是筛选“具备系统思维”的工程师而不是只会写接口或只会调样式的“零件工”。1.2 从命题风格反推B站的技术栈倾向2019年这个时间点B站的技术栈已经很有代表性了。Java在后端服务里占主导地位Go开始在部分高并发模块里渗透前端是Vue的中坚阵地但也在探索TS和工程化体系移动端以原生Android/iOS为主Hybrid方案负责运营活动页运维层面Docker和Kubernetes已经进入生产实践阶段。这套笔试题的考点分布基本就是照着这套技术栈画的。我当时把四个方向的题目全部过了一遍发现一个规律选择题和填空题考的是“你知不知道”简答题和编程题考的是“你会不会用”。前者决定了你能不能进下一轮后者决定了你能拿到什么评级。很多基础不错的人栽在选择题上原因不是不会而是踩中了命题人设计的“易混淆选项”。这个后面细说。2. 前端方向真题复盘与核心考点解析2.1 高频考点事件循环、作用域、HTTP缓存前端方向的题目里JavaScript基础占了将近四成。事件循环机制几乎是必考的而且B站特别喜欢考“async/await Promise setTimeout混合执行顺序”这种题。我当时拿到的那道题大概长这样代码里有setTimeout、Promise.resolve().then()、async函数里的await、还有console.log问输出顺序。这类题的答题关键是把微任务和宏任务的队列关系理清楚。同步代码先执行微任务在每一个宏任务结束之后清空await后面的代码相当于被Promise.then()包裹。实际笔试的时候我建议大家先画一个简单的表格把“同步任务/微任务/宏任务”分列然后逐个事件入表最后按序输出基本不会错。比在脑子里硬转靠谱得多。HTTP缓存也是一道必考题。B站这种视频平台对缓存策略极其敏感静态资源、接口数据、视频分片用的缓存策略完全不同。题目通常会给一组响应头问Cache-Control、Expires、ETag、Last-Modified的优先级和协商流程。这里有个容易踩坑的点Cache-Control和Expires同时存在时Cache-Control优先ETag和Last-Modified同时存在时服务端会先校验ETag。很多人把优先级搞反就是因为只背书不看实际请求过程。2.2 编程题手写防抖节流与弹幕布局前端编程题里防抖和节流是出现频率最高的题没有之一。B站这道题我记得是让手写一个防抖函数并且要求支持立即执行版本。这题表面上看是考闭包和定时器实际上考的是对“事件触发频率”的理解。视频网站里搜索框输入、窗口resize、滚动加载全都要靠防抖节流来控制性能开销。防抖的核心是“每次触发都重置定时器”节流的核心是“固定时间间隔内只执行一次”。我当时在答案里写了两版一版是常规的setTimeout实现另一版是用时间戳实现立即执行版本。时间戳版本的关键在于记录上次执行时间下次触发时如果时间差大于阈值就立即执行否则设置定时器延后执行。这道题能拿满分的人通常还会在答案里提到requestAnimationFrame在高频动画场景下的替代方案这种细节很加分。弹幕相关题目出现频率也很高毕竟弹幕是B站的灵魂功能。有一道题是问弹幕渲染的性能优化方案。常规答案包括用CSS3 transform替代top/left修改位置、开启GPU加速、限制同屏弹幕数量、对弹幕进行DOM复用等。进阶一点的答案会说“把弹幕绘制放到Canvas里用requestAnimationFrame批量渲染”以及“按弹幕轨道进行碰撞检测避免重叠”。你能写到哪一层直接反映你平时有没有真的调过线上性能问题。2.3 框架题目Vue响应式原理与组件通信Vue题目里响应式原理是一个绕不开的点。当时B站出的题是“Vue 2.6中修改数组的索引值视图会不会更新为什么”这题考的是Object.defineProperty对数组方法的拦截机制。Vue 2对数组的拦截是通过重写push、pop、shift、unshift、splice、sort、reverse这七个方法来实现的直接改arr[0] xxx不会触发视图更新所以答案是“不会”。这个坑在真实业务里也经常踩尤其是从接口拿数据后直接改数组某个字段发现页面没变然后一脸懵地到处找原因。解决方案是用Vue.set或者展开运算符创建新数组。面试官如果继续追问“Vue 3为什么就不会有这个问题”你可以回答Proxy直接代理整个对象对数组索引修改也能被监听到同时Proxy还能监听到属性的动态增删性能也更好。组件通信这道题比较常规父传子用props子传父用$emit兄弟组件可以用事件总线复杂状态用Vuex。但B站每年都会在组件通信里加一道跟业务场景结合的题比如“弹幕组件要怎么设计才能不阻塞主视频组件的渲染”。这种题的考察点在于你是把组件通信当作API背还是真的理解组件边界和渲染时机。3. 后端方向真题复盘并发、缓存与一致性3.1 Java基础与并发编程题后端方向的重头戏是Java题目从JVM内存模型一直覆盖到Spring框架。有一道我至今印象深刻的题volatile关键字能保证原子性吗这题是经典的“挖坑题”。volatile保证的是可见性和有序性不保证原子性。如果你回答“能保证线程安全”那就基本告别这轮笔试了。正确的理解方式是volatile修饰的变量每次读取都从主内存拿最新值每次写入都立即刷新到主内存所以它解决的是“一个线程写、多个线程读”场景下的可见性问题。但如果是count这种读改写操作多个线程同时执行时中间状态还是会丢失必须配合synchronized或AtomicInteger。我在答案里额外写了一句“volatile的典型应用场景是状态标志位和双重校验锁中的instance字段”这应该是加分点。并发编程这part还考了ConcurrentHashMap的实现原理。2019年的版本问的是JDK 1.8和1.7的区别1.7用分段锁1.8用CAS synchronized锁链表头节点。顺带还问了put流程先算hash定位桶如果桶为空就直接CAS写入如果不为空就锁住头节点然后遍历链表或红黑树。这个知识点在后端面试里重复率极高我建议把源码级别的执行流程背下来不要只记结论。3.2 缓存穿透、击穿、雪崩的应对方案B站这种流量级别缓存题如果不考才奇怪。这套题对着三个场景挨个问了一遍缓存穿透、缓存击穿、缓存雪崩分别怎么解决。穿透的解决方案是布隆过滤器加参数校验把不存在的key直接挡在缓存层之外。击穿的解决方案是热点key不设过期时间或者用互斥锁保证只有一个线程去查数据库。雪崩的解决方案是设置过期时间时加随机值避免大批key同时失效同时用熔断降级保护数据库。这里有个容易被忽略的细节缓存和数据库的一致性怎么保证。我当时在答案里写的是“先更新数据库再删除缓存”并解释了为什么不是“先删缓存再更新数据库”——因为后者在并发场景下会产生缓存中持续读到旧数据的窗口期。这种细节通常会被面试官专门圈出来追问所以要能解释清楚“为什么”。3.3 数据库索引与SQL调优数据库题目考了一道典型的慢查询优化题一个订单表数据量到千万级之后SELECT * FROM orders WHERE user_id ? AND status ? ORDER BY create_time DESC LIMIT 10变慢了问怎么优化。标准答案分几步第一联合索引(user_id, status, create_time)注意最左前缀原则第二避免SELECT *只查需要的字段第三如果业务允许用id做延迟关联。这题很容易遗漏的点是“为什么create_time要放在索引的第三位”。原因是它在WHERE条件里是排序字段放在联合索引里可以直接利用索引有序性避免filesort。如果只建(user_id, status)索引排序还是要走文件排序性能提升有限。我当时还踩过一个坑在索引列上用了函数比如WHERE DATE(create_time) 2019-09-01索引直接失效。这种细节如果笔试里不答出来面试官会觉得你写的SQL都只是“能跑”而已没有“会调”的意识。3.4 分布式系统设计与消息队列分布式那道题我记得很清楚设计一个支持百万级同时在线的弹幕系统要求弹幕延迟低于500ms。这题没有唯一答案考察的是你有没有完整的技术选型思路。我的答题结构是客户端通过WebSocket长连接接入弹幕网关网关按直播间ID做哈希路由到对应的弹幕房间服务弹幕消息先写Kafka削峰消费端批量写入Redis的有序集合再推送到同一个直播间内的所有连接。架构层面用分层设计把“连接管理”“消息处理”“消息存储”拆开每一层都可以独立扩容。读多写少的场景Redis的ZADD和ZRANGEBYSCORE天然适合做弹幕按时间排序和分页拉取。这道题拿高分的要点是除了写对组件名还要说出每个组件解决的具体问题。比如“为什么要用WebSocket而不是轮询”——因为弹幕延迟要求高轮询的请求开销和延迟都不可控比如“Kafka的分区键要怎么设计”——按直播间ID分区保证同一个直播间的弹幕顺序可控。这些因果关系能体现你真做过设计而不是背了个架构图。4. 运维方向真题复盘稳定性和效率是第一要义4.1 Linux命令与故障排查必考题运维方向的题目特别务实Linux命令考察占了很大一块。我记得有一道是给了一段线上故障描述某个Java进程CPU飚到100%请求大面积超时问怎么排查。这题的完整排查链路是先用top找到高CPU进程PID再top -Hp PID定位到具体线程ID转换成十六进制用jstack PID | grep -A 30 线程ID打印线程栈找到对应的业务代码位置。这里有个操作顺序的问题很多人第一步就jstack但如果不先定位线程直接抓到的栈对不上高CPU线程分析效率极低。正确顺序一定是“先定位再抓栈”。那道题还追问了一句“如果是频繁Full GC导致的CPU飙升你会怎么看”答案是jstat -gcutil PID看FGC和FGCT的变化趋势以及用jmap -dump导出堆快照分析对象引用链。B站这套卷子还考了awk和sed的现场应用。题目是有个10GB的访问日志格式是IP 时间 请求路径 状态码统计每个IP的访问次数并取Top 10。标准命令是awk {print $1} access.log | sort | uniq -c | sort -rn | head -10。这题看着简单但很多人会在uniq -c之前忘记sort导致统计结果完全错误。真题经验告诉我们常见的文本处理三板斧一定要练到手起刀落。4.2 容器化与Kubernetes基础概念2019年考容器其实有点超前了但说明B站那时候已经在布局容器化。题目考的是Docker镜像和容器的区别以及Kubernetes里Pod的调度单位。镜像是一个只读模板容器是镜像运行时的实例可以理解成“类和对象”的关系不过这个容器运行层的隔离性是通过Linux Namespace和Cgroup实现的。Kubernetes那道题是如果一台节点Node宕机了上面的Pod会怎么样答案是控制器如Deployment会在其他健康节点上重新创建Pod维持副本数但如果Pod是裸Pod没有控制器管理就不会自动恢复。这个知识点看概念的时候很容易忽略但在真实故障演练里极其重要——很多人以为Pod挂在K8s上就万事大吉其实没有控制器保障的Pod跟孤儿进程没什么区别。我当时在作业里进一步写了“节点驱逐的两种场景”节点失联超过pod-eviction-timeout默认5分钟节点上的Pod会被标记为Terminating并重新调度。这个细节被一个做运维的面试官单独标记过算是实打实的加分项。4.3 监控告警体系从Zabbix到Prometheus监控相关的题考的是思路而不是工具操作。题目问一个视频网站的核心监控指标有哪些分前端、后端、数据库三块写。前端看页面加载时长、白屏时间、接口成功率后端看QPS、RT、错误率、JVM堆内存数据库看连接数、慢查询数、主从延迟。这些指标不是拍脑袋想出来的每一个都对应一类用户可感知的故障。我答题的时候额外补充了一个观点监控告警必须分等级P0是核心链路不可用要立刻电话通知P1是功能异常但不至于完全不可用要30分钟内响应P2是指标升高但不影响用户发工单跟进。很多团队的告警是“一锅端”什么级别的告警都往群里丢结果真正出事的时候反而没人关注。这种工程管理上的细节笔试里答出来会让人觉得你有实战经验而不是只会装监控组件。Prometheus的题主要是概念题Pull模型和Push模型有什么区别为什么Prometheus默认用Pull。答案核心是Prometheus通过HTTP周期性拉取指标能避免客户端崩溃导致数据丢失而且可以在服务端统一配置采集策略。不过实际场景中对于短生命周期任务或网络隔离环境也需要Pushgateway做指标中转。这个补充很重要因为很多答Pull模型优势的人没想过为什么官方还要提供Pushgateway。4.4 网络排查CDN与DNS视频平台对CDN依赖度极高所以网络题一定不会少。B站这套卷子里有一道DNS劫持的排查题用户反馈访问部分视频页面时被跳转到广告页怎么定位。答案路径是切换DNS服务器看是否复现如果换DNS后恢复正常说明是Local DNS被污染再全链路排查检查HTTP响应头是否有异常字段抓包看TCP连接的目标IP是否为CDN节点IP。CDN题目里问了一个很实际的问题命中率上不去的原因有哪些。答案包括缓存时长配置过短、URL带随机参数导致缓存碎片化、 Range请求场景下缓存未配置切片等。这类问题需要你在真实生产环境里看过CDN控制台的命中率曲线才有体感所以笔试里能写出几条贴近业务场景的原因会比对概念更打动人。5. 移动端方向真题复盘性能与体验的双重考验5.1 Android生命周期与内存泄漏移动端的题对Android和iOS都有覆盖Android占大头。生命周期题几乎是送分题Activity A启动Activity B两个Activity的生命周期回调顺序以及点击返回键时的顺序。标准答案是A.onPause → B.onCreate → B.onStart → B.onResume → A.onStop返回时是B.onPause → A.onRestart → A.onStart → A.onResume → B.onStop → B.onDestroy。这题看着简单但有一个很容易被忽略的点A.onStop方法在B完全遮住A之后才会执行而A.onPause在B可见之前就会执行。所以如果你在onPause里做重量级操作比如保存大量数据就会拖慢B的启动速度。这个细节跟性能优化直接挂钩也是B站这类“视频App”移动端面试比较在意的地方。内存泄漏那道题是经典的“Handler造成Activity泄漏”内部类Handler持有Activity引用如果Handler里有延迟消息在消息处理之前Activity被销毁Activity就无法被回收。解决方案是用静态内部类加WeakReference或者在onDestroy里removeCallbacksAndMessages。我在答案里顺手写了LeakCanary的检测原理通过WeakReference监控Activity的回收情况这道题基本就稳了。5.2 列表流畅度与图片加载优化B站App的信息流是用户日常刷得最多的场景所以列表流畅度也是移动端重点考点。题目基本绕着RecyclerView的卡顿优化展开。答案要分层回答布局层面用setHasFixedSize(true)、避免嵌套线性布局数据层面用DiffUtil做增量更新图片层面用Glide的override指定加载尺寸、用thumbnail加载占位图、用skipMemoryCache(false)配合LRU内存缓存。图片加载这里特别容易踩坑一张2000x2000的大图直接塞进列表即使只显示100x100的区域解码后占用的内存也是按原图大小计算的。所以Glide的override(100, 100)不是简单的显示缩放而是直接决定了解码采样率能显著降低内存占用。这种知识如果你只看SDK文档不调优基本发现不了。启动速度优化也是高频方向。有一道题是App冷启动时间过长可能的原因有哪些。答案有Application里做了太多同步初始化、冷启动时加载了不必要的SDK、首页布局层级过深、资源文件过大导致I/O耗时。解决方案是延迟初始化非核心SDK、用异步初始化框架启动器、用App Startup库简化初始化流程。2019年时App Startup还比较新如果写在答案里消息面的面试官会眼前一亮。5.3 跨端方案与Hybrid调试B站的移动端并不是纯原生技术栈运营活动页、部分频道页是用跨端方案做的。所以题目里有一道Hybrid页面加载慢常见瓶颈和优化手段是什么。瓶颈主要在网络请求、WebView初始化、JS注入和资源加载几个环节。优化手段包括预先初始化WebView实例、离线包预加载、复用全局WebView池、开启硬件加速、使用shouldInterceptRequest拦截资源请求并走本地缓存。这里有个非常实用的经验WebView首次启动的耗时瓶颈通常不在加载网页而在创建WebView实例本身。所以像淘宝、B站这类App会在启动时就预创建一个空闲的WebView躺在后台等用户真正打开H5页面时直接复用能让首屏速度提升一大截。笔试里能说到这一层的基本就是正儿八经搞过Hybrid性能优化的了。5.4 网络层弱网适配与流量优化移动端网络题是我当时最头疼的部分。B站出了一道“视频App在弱网环境下要怎么做好体验优化”。这题的核心词汇是“降级”。弱网下自动切换清晰度从1080P降到480P是体验兜底视频预加载策略要改成仅在Wi-Fi下预加载避免消耗用户流量请求超时时间要动态调整不能用一个固定值。另外还有一个考点是断点续传的原理下载视频时在HTTP请求头里带上Range: bytesxxx-xxx服务器返回206状态码客户端把分片写入本地文件。这个机制对于大文件下载和视频播放进度条拖动都至关重要。如果你能把这个机制跟移动端播放器的拖动体验结合起来描述这道题的答案就非常完整了。6. 答题策略与复盘笔记这些经验能直接复用6.1 时间分配选择快准狠编程留时间这套笔试题量不小我当时估算了一下如果每一道选择题都纠结后面的编程题肯定写不完。所以时间分配策略非常重要选择题和填空题部分读完题目10秒内没有明确答案先标记起来跳过简答题按点作答写清关键词就行不用长篇大论编程题留足一个小时因为编码、测试、修改语法错误都需要时间。我个人的建议是“30分钟做客观题30分钟做简答60分钟做编程最后10分钟检查”。客观题里那些压轴难度的题往往是命题人故意放到最后干扰心态的跳过去不可惜。编程题反而是拉开差距的关键你只要把题做出来哪怕不是最优解拿到面试机会的概率也远大于前面选择题全对但代码全空的人。6.2 编程题的规范度细节我见过很多“思路完全正确但代码零分”的卷子原因是犯了一些低级错误没有考虑边界条件、变量命名不清、不写注释、缩进混乱。笔试阅卷通常不会真去运行代码而是人工看代码逻辑和书写规范。所以哪怕时间再紧也要保证代码结构清晰。编程题如果遇到“字符串判空”“数组长度为0”这类边界条件一定要写进代码里。这会让阅卷人觉得你考虑问题周全而周全恰恰是大厂对工程师的基本要求。还有一个细节是如果题目要求提供多种解法不要只写一种。比如排序题你可以写快排然后补充说“待排序数组基本有序时可以改用插入排序”这种对比感能体现你的算法视野。6.3 复盘比刷题更重要我踩过的坑和修正思路考完这套题之后我做了一次完整的错题复盘发现失分的题其实集中在两类一类是概念模糊题比如volatile和Cache-Control优先级这些是对底层机制理解不透导致的另一类是场景覆盖不全题比如弱网优化只想到降低清晰度没想到预加载策略和超时时间调整。针对概念模糊题我的修正方法是把每个考点画成一张“场景机制后果”的三列表格。以Cache-Control为例场景是浏览器缓存静态资源机制是根据max-age计算缓存有效期后果是配置过短导致请求量大。这种方式能帮助你把零散的知识点连成体系而不是死记硬背。针对场景覆盖不全题我的修正方法是刻意训练“方案枚举”的能力。每遇到一个性能优化题先把所有可能的优化层次列出来代码层、资源层、网络层、架构层。然后逐层填空补全没考虑到的手段。这个方法我后来也用在系统设计题上效果非常明显。6.4 后续学习路线笔试不是终点如果你这次笔试过了接下来还有面试如果没过也不代表你不行只是这次考察的知识点恰好没覆盖到你熟悉的部分。但无论结果如何我都会建议把笔试中暴露出的知识盲点整理成一个“补全清单”按照三个优先级去补第一优先级是底层基础比如操作系统、网络协议、数据结构第二优先级是框架原理比如Vue响应式、Kafka消费模型、K8s调度器第三优先级是业务场景实战比如高并发设计、缓存一致性、弱网优化。这套笔试的价值不在于你得了多少分而在于它帮你画了一幅“大厂技术岗能力地图”。把地图上的每一个坐标都搞明白比刷十套题都有用。我自己后来带团队面试时也会参考这套题库的逻辑来出题——先看基础是否扎实再看能不能把基础应用到复杂场景里。基础不牢的项目经验再花哨也不太敢要基础扎实的碰到没做过的业务也能快速上手。7. 个人总结这套题给我留下的三个认知第一个认知是B站的笔试题特别强调“业务感”。同样是考缓存通用题库可能只问Redis的数据结构但B站会把弹幕的场景套进去问你怎么保证有序、怎么控制延迟。所以刷题的时候不要只刷知识点要把知识点放回业务场景里去理解这才是大厂笔试真正筛选的东西。第二个认知是四个方向其实是一条链路的四个断面。前端题里的HTTP缓存、后端题里的CDN回源、运维题里的DNS解析、移动端题里的弱网优化全是同一条“用户请求视频”链路上的不同环节。谁能把这条链路串起来理解谁就能在笔试和面试里答出“超出岗位边界”的答案这种答案最容易拿高分。第三个认知是笔试复盘的价值高于刷题数量。我后来做了面试官经常能看到一些候选人刷了大量LeetCode但问到底层机制就答不上来。相反那些把一套真题吃透、能把每题背后的原理和场景讲清楚的人反而更容易通过。这也是我写这篇复盘文章的初衷——与其走马观花地刷十套题不如把一套有价值的题榨干吃透。最后分享一个小技巧准备这类笔试之前去找目标公司的技术博客和开源项目看一圈。B站当年开源的各类组件和Kotlin协程实践其实都是自家笔试题的“题库来源”。产品用什么技术栈、团队在解决什么问题、踩过什么坑看一圈下来你对这份卷子会更有底。
返回列表