尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

爱奇艺2019秋招大数据开发笔试题B卷解析与备战攻略

爱奇艺2019秋招大数据开发笔试题B卷解析与备战攻略 又到秋招季总有学弟学妹跑来问我大数据开发方向的笔试题到底怎么准备我的建议向来是同一个——先找一套完整的大厂真题从头到尾认真做一遍比漫无目的地刷几个月短视频里的“面试技巧”有用得多。如果你问哪套题最适合用来摸底我通常会推荐爱奇艺2019秋招大数据开发方向笔试题B。原因很简单这套题覆盖面够广Java基础、并发、大数据组件、Linux命令、SQL、手写代码全都有难度梯度也算合理特别适合当成一张“能力体检表”来用。我当年把这套题的回忆版翻来覆去做了三遍后来去其他公司面试时发现很多考点是相通的。今天就把我对这套题的分析、做题过程中查漏补缺的知识点以及从这套题里反推出来的秋招备战思路一次性整理出来。不需要你基础多好只要你有一定 Java 和 Hadoop 生态的使用经验这篇文章就能帮你把零散的知识串成一条线。1. 这套笔试题为什么值得反复拆解1.1 从岗位JD反推考察重点想弄明白一套笔试题为什么这么出最直接的方法是看岗位 JD。大数据开发这个岗位在爱奇艺这类视频平台日常面对的绝不仅仅是“写几个 MapReduce”那么简单。视频网站每天产生海量用户行为日志点击、播放、暂停、拖拽、搜索、评论、付费这些日志经过采集、清洗、ETL、数仓建模、指标计算最终支撑推荐、广告、会员运营等业务方做决策。所以这个岗位要求的能力是复合的既要懂 Java 这种主力开发语言又要熟悉 Hadoop、Spark、Flink、Kafka 这套大数据生态组件还要能写复杂的 SQL 和 Shell 脚本偶尔甚至要自己调 JVM 参数、排查线上 OOM。爱奇艺这套笔试B的考点布局基本上就是按照这个能力模型来的。很多同学拿到试卷第一反应是“怎么考这么多 Java 基础”觉得大数据开发不应该只考框架吗这个认知在面试里很吃亏。大数据框架本身就跑在 JVM 上Hadoop、Spark、Flink、Kafka 的源码全是 Java/Scala 写的你如果连 HashMap 的结构、并发编程的基本机制都说不清楚面试官很难相信你能读懂框架源码、能定位线上问题。所以 Java 基础部分不是凑题数是筛人。1.2 题型分布与答题节奏从各个渠道流传的回忆版来看B 卷大致分为四类单选题、多选题、简答题、编程题。单选多选主要覆盖 Java 基础、并发、JVM、Linux 命令、SQL 语法、大数据组件原理简答题一般会有一两道让你描述 MapReduce 流程、Spark 任务执行流程或者数据倾斜解决方案的题编程题则是传统的数据结构与算法题偶尔会结合大数据场景。这里有一个很关键的答题节奏问题选择题不能恋战。每道选择题的分值并不高但如果在两道争议题上死磕十分钟后面编程题的时间就会被压缩。我记得当时给自己定的规则是单道选择题最多两分钟拿不准的先标记等编程题写完再回头蒙。整套题里真正的拉分项永远是编程题和简答题不要在基础题上丢了西瓜捡芝麻。1.3 B 卷背后的“套卷机制”标题里的B不是随便标的。大厂笔试通常会在同一时间安排多套试卷题目一样但顺序打乱或者抽选不同子题集目的就是防止前后排考生对答案。这也是为什么你在网上看到同样的“2019秋招大数据开发笔试题”有人说是 A 卷、有人说是 B 卷题目却大同小异。准备的时候不用纠结自己考的是哪一套考点就那么多把核心知识点全部过一遍任何卷子都能应付。2. Java与并发看起来是选择题实则是淘汰主战场2.1 为什么大数据开发要死磕 Java 基础大数据开发的日常工作中Java 不是“偶尔用一下”的语言而是主力语言。你用 Spark 写分析任务虽然可以用 Scala 或者 PySpark但阅读源码、调优、排查问题最终都会落到 Java/JVM 层面。爱奇艺这套笔试题里Java 相关题目占比相当高而且考察得非常细。这不是为难人而是想筛掉那些只背框架 API、不懂底层原理的简历选手。我之前帮部门做过校招面试发现一个明显的规律Java 基础扎实的人大数据框架学得也快因为 Spark 的 RDD、DataFrame 也好Flink 的 Watermark、Checkpoint 也罢本质上都是 Java 并发、集合、网络编程的封装。你明白 HashMap 的扩容原理就更容易理解 Spark 的 shuffle 为什么会产生大量小文件你明白 JVM 内存模型就更容易理解为什么大数据任务要设置 executor memory 参数。2.2 HashMap、ConcurrentHashMap 与并发安全的底层逻辑集合框架是 Java 基础题里的“必考点”爱奇艺这套题也不例外。比较有代表性的考察方式是这样的问题JDK 7 和 JDK 8 中 HashMap 的实现有哪些差异为什么 HashMap 在并发场景下不安全这个题几乎每年都出现但能答全的人不多。正确的答题框架应该是JDK 7 的 HashMap 底层是数组加链表插入元素时采用头插法扩容时多线程并发 put 可能形成环形链表一旦 get 的时候发生死循环CPU 直接飙满。JDK 8 改成了数组加链表加红黑树链表长度超过 8 且数组长度超过 64 时树化插入改用尾插法从机制上避免了死循环问题但并发场景下仍然可能出现数据覆盖、size 计数不准确等问题。所以并发场景要用 ConcurrentHashMap。如果再追问 ConcurrentHashMap 的原理JDK 7 是分段锁把整个 Map 分成 16 个 Segment每个 Segment 是一把锁JDK 8 放弃分段锁改用 CAS 加 synchronized 锁住桶的首节点锁粒度更细并发度更高。这种层层递进的答法比背几句“线程安全基于 CAS”的面试话术要显得有底气得多。2.3 JVM 与 GC 的考察方式JVM 相关题目在 B 卷里也占据一席之地常见考法有内存区域划分、GC 算法、OOM 场景分析。这类题看起来很“后端”但大数据开发同样躲不开因为跑 Spark/Flink 任务时OOM 是出现频率最高的线上事故之一。我推荐用“画图加举例”的方式复习把堆内存、虚拟机栈、本地方法栈、方法区、程序计数器的职责先讲清楚然后结合一个具体场景——比如一个 Spark Executor 频繁 Full GC你会怎么排查一般思路是先用jstat看 GC 频率再用jmap导出堆内存快照用 MAT 分析哪个对象占内存最大。如果你能在笔试简答题里写出这个排查链路面试官对你的印象会明显不一样。GC 算法方面CMS 和 G1 的区别是高频考点。CMS 基于标记清除并发收集但会产生内存碎片G1 把堆划分成 Region基于 Region 做局部回收可以预测停顿时间。JDK 9 之后 G1 成为默认垃圾回收器JDK 17 以后 ZGC 开始普及这些演进脉络也可以顺带了解。2.4 数组与指针从 Java 数组到 C 指针的延伸搜这套题的同学经常会连着搜“数组和指针笔试题”说明这类题在笔试里出现频率很高。Java 里没有指针的概念但数组本身就是一种引用类型所以考题会围绕数组的拷贝、引用传递、内存分配展开。比如问题int[] a {1,2,3}; int[] b a; b[0] 100;此时a[0]是多少答案是 100。因为b a赋值的是引用两个变量指向同一块堆内存修改 b 的元素等于修改 a 的元素。这是 Java 基础题里最经典的坑也是很多非科班同学容易忽略的点。C 语言的指针与数组又是另一套完全不同的玩法数组名是常量指针a[i]本质上是*(a i)的语法糖。虽然大数据开发岗位基本不会让你写 C但笔试偶尔会出这类题来考察计算机基础是否扎实。应对方式很简单把指针加减、指针数组和数组指针、函数指针这几个概念过一遍即可不需要深入。2.5 Java 基础部分的备战方式针对这套题折射出来的 Java 考点我的建议是不要只看面经要自己动手做实验。比如 HashMap 的树化条件你就写一段代码往 HashMap 里插入哈希值相同的 key观察链表什么时候变成红黑树再比如 volatile 的可见性你写一个多线程程序验证一下不加 volatile 时死循环的现象。这些实验做完之后你会发现很多题不再需要“背答案”而是凭理解就能推导出来。3. 大数据组件原理MapReduce、Spark 与 Kafka 的考察重心3.1 视频平台的真实数据链路爱奇艺这类视频平台的数据链路很有代表性。以一次用户播放行为为例客户端上报播放日志到 KafkaFlink/Spark Streaming 消费 Kafka 数据进行实时清洗与此同时离线任务把日志落盘到 HDFS通过 Hive/Spark SQL 做 ETL按天构建数仓分层最终产出播放量、完播率、观看时长等核心指标。理解了这条链路你就明白为什么笔试题会同时考察 Kafka、Flink、Spark、Hive 这些组件。它们不是孤立的知识点而是同一套数据流转过程中的不同环节。考试的时候别只顾着背每个组件单独的特性能讲清楚一条数据从产生到最终形成报表的完整流转过程才是面试官真正想看到的。3.2 MapReduce 与 Shuffle必考的流程题MapReduce 的 Shuffle 过程几乎是大数据笔试的“钉子户”。爱奇艺这套题简答题部分很可能会有这么一道描述一个 MapReduce 任务从提交到完成的完整流程。答题不能只写“Map 阶段输出中间结果Reduce 阶段汇总”那样太单薄。完整的回答应该包含这几个阶段InputFormat 对输入数据进行切分生成 InputSplitRecordReader 将数据解析成 key-value 对Mapper 处理数据后map 输出先写入环形缓冲区默认大小 100MB达到 80% 阈值时触发溢写溢写前会做分区和排序默认按 key 的哈希值分区溢写会产生多个小文件之后执行归并排序合并成一个大文件同时做 Combiner 局部聚合Reduce 端通过 pull 方式拉取属于自己的分区数据做一次完整的 shuffle然后再进行分组排序最终调用 Reduce 函数。一个容易踩坑的细节是很多同学分不清“分区”和“分组”的区别。分区是决定某个 key 进入哪个 Reduce 分区分组是决定哪些 key 值被认为是同一个 key从而调用一次 Reduce 方法。在 Hive 中group by作用于分组而 MapReduce 的分区数决定 Reduce 个数两者不是说一回事。3.3 Spark 核心RDD 依赖、Stage 划分与数据倾斜Spark 的考察重点集中在 RDD 依赖关系、Stage 划分、Spark SQL 和调优方向。宽依赖和窄依赖的区别是必考题。窄依赖是指父 RDD 的每个分区最多被子 RDD 的一个分区使用典型操作有 map、filter、union宽依赖是指父 RDD 的每个分区可能被子 RDD 的多个分区使用典型操作有 groupByKey、reduceByKey、join。窄依赖的算子不需要 shuffle可以在同一个 Stage 内完成宽依赖需要 shuffle是 Stage 划分的边界。为什么这个知识点如此重要因为数据倾斜通常就发生在宽依赖的算子上。比如用 groupByKey 做 WordCount某个单词出现次数特别多对应的 Reduce 任务就会长时间运行甚至 OOM。解决方案主要是加随机前缀进行二次聚合、两阶段聚合、调整并行度、开启spark.sql.adaptive.enabled让 Spark 自动做倾斜 join 优化。笔试题如果出“Spark 任务运行缓慢你怎么排查”答题思路应该是先看 Spark UI识别出哪个 Stage 耗时最长再点进去看是某个 Task 卡住还是所有 Task 都慢如果是单个 Task 慢基本可以断定是数据倾斜再用sample算子抽样检查 key 分布最后根据倾斜情况选择加随机前缀或者调并行度。3.4 Flink 和 Kafka如果考到会这么出题虽然 2019 年的时候 Flink 还没有如今这么普及但爱奇艺的实时计算场景早就存在了所以这套题里出现 Flink 相关题目也不意外。Flink 常见的考点是事件时间与处理时间的区别、Watermark 的作用、状态后端、Checkpoint 机制。Kafka 的考点相对更基础分区与副本机制、ISR 与 ACK 参数acks0/1/all、消费者组与分区分配策略、消息不丢失的保证。有一个很经典的连环题“Kafka 如何保证消息不丢失”答题要从生产者、Broker、消费者三个层面分别说明生产者设置acksall并开启重试Broker 设置min.insync.replicas2消费者处理完成之后再提交 offset。能分三层答基本能拿满分。3.5 数仓分层与建模类简答题大数据开发笔试里最常见的一类简答题是谈谈你们数仓是怎么分层的各层的作用是什么一般回答是 ODS、DWD、DWS、ADS 四层模型。ODS 层是源数据直接落地保持与业务库一致不做任何加工DWD 层做清洗、规范化、维度退化统一命名规范DWS 层按主题汇总比如按用户、商品、流量主题加工成宽表ADS 层是面向报表和应用的数据直接对接业务方。这道题考察的不只是概念还有你对业务的理解。能结合视频平台举出具体例子最好比如“播放记录表属于 ODS 层清洗后的播放明细表在 DWD 层按用户维度汇总的观看统计表在 DWS 层最终每日报表在 ADS 层”。笔试的时候如果能写出这种层级加例子而不是只背四层定义是一个不小的加分项。4. Linux与SQL笔试中的“隐形大户”4.1 Linux 命令题总是被低估很多同学备战大数据笔试时会把精力放在算法题和框架原理上对 Linux 命令不屑一顾觉得“反正工作之后再学也不迟”。但大数据开发这个岗位日常工作的主战场就是 Linux 服务器你不会用top、free、df、ps连排查问题都无从下手。所以笔试里出 Linux 题是非常合理的而且考察的点往往贴合实际场景。常见的出题方式不是问“ls命令的-l参数是什么意思”而是给你一个实战场景服务器 CPU 飙升你怎么找出是哪个进程干的标准答案是先用top查看进程 CPU 占用率再用top -Hp [pid]查看具体线程配合jstack导出线程快照找到出问题的代码位置。另一个高频场景磁盘空间不足怎么快速找到大文件df -h看整体使用率du -sh *层层排查目录再用find / -type f -size 1G直接列出大于 1GB 的文件。这些命令在大数据运维里天天都要用笔试考它们就是考察日常积累。4.2 grep、awk、sed 三件套的实战用法文本处理三件套是 Linux 命令题的重头戏。比如日志文件access.log的每一行是“IP 地址 访问时间 请求路径 状态码”问你如何统计访问次数最多的前 10 个 IP。awk {print $1} access.log | sort | uniq -c | sort -rn | head -10这条命令的每一步都值得拆开讲awk {print $1}是取第一列sort是排序让相同的 IP 排在一起uniq -c统计去重后每项的出现次数sort -rn按数字逆序排序head -10取前十条。还有一类常考题是 sed 的原地替换把文件里所有http替换成https并且修改原文件。sed -i s#http://#https://#g config.txt这里没用常见的/作为分隔符而是用了#主要原因是 URL 里本身包含/直接用/做分隔符需要转义写成#可以少踩很多坑。这种细节就是笔试选择题里的加分点。4.3 SQL 窗口函数分组 TopN 是最高频考点大数据开发笔试的 SQL 题基本绕不开窗口函数。它的典型场景是求每个部门工资最高的员工、求每个用户最近一笔订单、求连续登录 N 天的用户。窗口函数的核心语法就一条row_number() over (partition by 分组字段 order by 排序字段 desc) as rk以“求每个用户的最近 3 笔订单”为例select user_id, order_id, order_time from ( select user_id, order_id, order_time, row_number() over(partition by user_id order by order_time desc) as rk from orders ) t where rk 3;这里特别需要提醒一个新手常犯的错误子查询里的rk字段不能在同一个查询的 where 条件里直接引用比如where row_number() over(...) 3会直接报错因为窗口函数是最后执行的。必须包一层子查询在外面过滤。这个坑在笔试里出现频率特别高因为它考察的是执行顺序的理解而不是语法背诵。4.4 连续登录问题的两种解法“求连续登录 3 天以上的用户”是另一道高频 SQL 题它有很多变形比如连续签到、连续购买。核心解法是用date_sub做日期差值。select user_id from ( select user_id, login_date, row_number() over(partition by user_id order by login_date) as rn from user_login group by user_id, login_date ) t group by user_id, date_sub(login_date, rn) having count(1) 3;思路是这样的先把同一个用户每天的连续登录日期减去行号如果日期是连续的那么差值会保持不变如果中间断了差值就会变。所以group by user_id, 差值之后count 大于等于 3 的组就是连续登录至少 3 天的用户。这里有个细节login_date可能同一天有多条记录比如用户一天登录了两次直接算行号会把同一天的重复记录也算进去导致误判。所以要先group by user_id, login_date去重再做窗口计算。这个去重的步骤是很多参考答案里没写出来的但实际笔试时很容易中招。5. 编程题是拉分项从 TopN 到滑动窗口的破题路径5.1 编程题到底在考什么笔试的编程题不会让你写一个完整的 MapReduce也不会让你手写 Spark 算子。它的核心考察点还是数据结构和算法只是偶尔会套一层“大数据场景”的外衣。爱奇艺这套题的编程部分基本集中在数组、字符串、链表、堆、滑动窗口这些经典题型上。刷题的时候不要盲目追求题量先把每一类题型的套路吃透。比如“连续子数组最大和”是动态规划基础题“两数之和”是哈希表的典型应用“TopK”是堆的经典场景“最长无重复子串”是滑动窗口的标准模板。这四类题掌握之后笔试遇到新题至少不会完全懵。5.2 海量日志 TopK堆是最优解结合大数据场景的编程题最常见的是“在一个很大的文件里找出出现次数最多的 TopK 个单词”。纯算法题版的问法是“求一个无序数组里的前 K 大元素”。public int[] topK(int[] nums, int k) { PriorityQueueInteger heap new PriorityQueue(k); for (int num : nums) { if (heap.size() k) { heap.offer(num); } else if (num heap.peek()) { heap.poll(); heap.offer(num); } } int[] res new int[k]; for (int i 0; i k; i) { res[i] heap.poll(); } return res; }这里用了一个大小固定为 K 的最小堆遍历数组时只要当前元素比堆顶大就替换堆顶这样堆里始终维护着当前最大的 K 个数时间复杂度 O(n log k)。面试如果追问“数据量特别大怎么办”可以补充说明文件过大无法一次性加载到内存时先做哈希分片把大文件拆成多个小文件分别统计每个小文件的 TopK最后再归并。这道题还有一个高频变种求第 K 大的元素。用快速选择算法平均时间复杂度 O(n)代码思路是在快排的 partition 基础上只递归处理包含第 K 大的一侧不做全量排序。如果笔试时间充裕写快选比写一堆更优雅。5.3 连续子数组最大和动态规划入门模板“最大子数组和”是 LeetCode 第 53 题也是笔试编程题里出现频率很高的一道因为它短小精悍能快速看出候选人的动态规划基本功。public int maxSubArray(int[] nums) { int cur nums[0]; int max nums[0]; for (int i 1; i nums.length; i) { cur Math.max(nums[i], cur nums[i]); max Math.max(max, cur); } return max; }核心逻辑就一行cur Math.max(nums[i], cur nums[i])。翻译成人话就是“当前最大子序列和”要么从当前元素重新开始要么带着前面的累加值继续加取两者较大值。cur维护的是以当前元素结尾的子数组最大和max维护的是全局最大和。这道题写出来很容易但想要在笔试里拿满分还需要在注释或者旁边写明“时间 O(n)空间 O(1)”这能体现你的算法复杂度意识。5.4 输入输出格式笔试翻车的高发区域代码写对了但是 0 分这类悲剧每年都在发生。原因绝大多数不是算法问题而是输入输出格式没处理好。牛客网这类平台和 LeetCode 不同LeetCode 已经帮你把函数签名定义好了你只需要填函数体牛客网需要你写完整的public class Main自己用Scanner读取输入再按指定格式输出。很多同学平时只刷 LeetCode不熟悉这种“自己处理输入输出”的方式笔试时一紧张Scanner 的循环读法都写错了。我建议在秋招开始前去牛客网上把近三年的真题模拟题都做几道专门练习完整的代码结构。记住一个通用模板import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc new Scanner(System.in); int n sc.nextInt(); int[] arr new int[n]; for (int i 0; i n; i) { arr[i] sc.nextInt(); } // 处理逻辑 System.out.println(result); } }还有一个容易被忽略的点有些题目要求输出结果保留两位小数比如System.out.printf(%.2f, result)有些要求多个结果之间用空格分隔最后一个后面不能有空格。这些细节在笔试环境里一旦出错会直接判定答案错误比算法没写出来还可惜。6. 从这套笔试反推秋招备战我的几点实践复盘6.1 原理与刷题的时间配比我见过太多人备战大数据开发笔试要么只刷算法题要么只看框架面经这俩都是极端。爱奇艺这套题给我的最大启发是它同时考察原理深度和代码熟练度两边的权重其实差不多。比较合理的安排是五五开一半时间用来深入理解 Hadoop、Spark、Kafka 的核心机制另一半时间用来刷算法题和 SQL 题。原理部分不要停留在“会用”层面要能用自己的话讲清楚 MapReduce 的 Shuffle 过程、Spark 宽窄依赖、Kafka 的 ISR 机制。SQL 部分不要只看题解一定要亲手在本地或者在线环境跑一遍。我自己复习时有一个笨但有效的方法把每个核心知识点抄在一张 A4 纸上只写关键词和流程箭头不看资料对着这张纸口述讲一遍。讲不出来的地方就是知识盲区回头再去看那块的源码或博客。这个方法坚持两周效果比反复读书好得多。6.2 笔试现场的答题顺序与时间切分真正坐在笔试考场里心态和平时刷题完全不一样。我总结了一套当时用着很顺的答题顺序先花一分钟扫一遍全部题标记出编程题的大致难度然后按顺序做选择题遇到卡壳的直接跳过选择题做完后先做会写的编程题再做简答题最后回头处理跳过的选择题和自己不熟悉的编程题。时间切分上我一般会把整个笔试时间的 50% 留给编程题30% 留给选择填空20% 留给简答。因为编程题是按通过用例给分的写出来大部分用例可能就能拿到 60% 到 80% 的分数这比在选择题上纠结半天的性价比高得多。6.3 复盘比刷题更重要做完一套题对照答案估分只是第一步更重要的是把错题涉及的每一个知识点都深挖一遍。我会为每道错题建立一个类似“问题是什么、涉及的知识点、根本原因、同类题型的解题模板”的卡片然后每周集中回顾一次。比如我在做 HashMap 相关题时错过一次“JDK 7 头插法和 JDK 8 尾插法的原因”这个点复盘的时候我就专门去看 JDK 8 的源码把putVal方法整个读了一遍又画了扩容前后链表结构的示意图。从那以后凡是遇到 HashMap 并发问题我基本不会再丢分。这种“以题带点、以点带面”的复盘方式比再刷十套新题更有效果。6.4 最后分享一点心态上的体会准备秋招笔试的过程确实枯燥尤其是当你发现同一道题做了三遍还是会错的时候很容易自我怀疑。但大数据开发这个方向本来考查的就是知识广度和深度并重一时半会儿记不全太正常了。我自己的体会是把每一次笔试都当成一次免费的学习机会题没做完不要紧关键是从中提炼出哪些知识点还没掌握、哪些代码模板还不够熟练下一次进场多拿几分就足够了。
返回列表