爱奇艺秋招大数据笔试题解析:从Java到Spark的考点与备考策略

爱奇艺秋招大数据笔试题解析:从Java到Spark的考点与备考策略 爱奇艺2019秋招大数据开发方向这套B卷我在整理的时候其实很有感触。它出的题目不算偏但覆盖面很广从Java基础到分布式计算再到数仓建模都有涉及几乎把大数据开发岗位日常要碰的东西都串了一遍。对于准备校招的同学来说这份卷子就像一个很好的“体检单”能帮你看清楚自己的知识体系哪里还有漏洞。我自己在带新人或者帮朋友做面试辅导的时候也经常拿类似的题目来做摸底。这篇文章我就从这套笔试题出发把里面涉及的核心知识点、容易踩的坑以及我个人的一些解题思路和备考经验一块儿聊聊。1. 先聊聊这套题背后的业务逻辑爱奇艺为什么要这么考很多同学拿到笔试题的第一反应是“赶紧刷题”但我觉得更聪明的做法是先想清楚一件事出题人到底在考察什么。爱奇艺这种体量的视频平台大数据开发岗位的工作内容和一般互联网公司相比有它的特殊性。1.1 视频平台的数据特征决定了考察方向爱奇艺的核心业务是视频内容的制作、分发和变现这意味着它每天要处理的数据量级非常大而且数据类型特别丰富。用户行为日志播放、暂停、拖动、退出、视频内容元数据标题、分类、标签、演员、广告投放数据、CDN分发日志、会员订单数据等等统统要汇聚到大数据平台上来。举个例子一个用户看一部电视剧这一条播放记录在后台就会产生至少几十个维度的指标包括播放时长、码率、清晰度、设备类型、是否拖拽、缓存命中情况等。每天几千万甚至上亿的用户在看视频产生的数据条目用“亿”来做计量单位都是保守的。所以爱奇艺的大数据开发同学日常做的最多的事情就是处理这些海量日志的采集、清洗、存储、计算和分析。这也就解释了为什么笔试题里会大量考察Kafka日志采集和消息中间件、HDFS分布式存储、Spark和Hive离线计算、Flink实时计算这些组件。因为这些东西就是日常工作台上的“锅碗瓢盆”你如果连这些工具都不熟那确实没法干活。1.2 从题目反推岗位能力模型这套B卷我整体看下来它其实在验证三个层次的能力。第一层是语言基础主要是Java。为什么考Java不考Python因为大数据生态里的核心组件比如Hadoop、Hive、Spark部分、Flink绝大多数是用Java或Scala写的底层源码是Java你要做二次开发、排查问题、调优不懂Java会很吃亏。而且很多公司的开发框架也以Java为主。第二层是计算引擎原理这部分是区分度的关键。能不能说清楚HDFS的读写流程、Spark的Shuffle机制、Hive的SQL底层怎么转化成MapReduce或Spark任务这些决定了你是一个“只会调API的调用者”还是一个“真正理解系统的开发工程师”。爱奇艺的题里明显偏向后者。第三层是工程能力和场景设计。比如给你一个视频播放日志统计的需求让你设计一套从数据采集到报表展示的完整方案。这种题没有标准答案考察的是你有没有真正在项目里从头到尾做过东西。把这三点想明白了再去复习每一道题你就能抓住重点而不是陷入知识点碎片化的死记硬背。2. 笔试核心考察模块知识点分布与解析这套B卷的知识点覆盖范围比较典型我大致把它分成六个模块下面逐个说。2.1 Java基础不只是语法更是并发和集合的底层机制Java基础在大数据笔试题里从来不是简单的语法考察而是集中在集合类、并发编程和JVM内存模型上。高频考点包括HashMap的底层实现、ConcurrentHashMap的分段锁机制、ArrayList和LinkedList的区别、线程池的核心参数含义、volatile和synchronized的区别、以及JVM的类加载过程和GC算法。我当时复习的时候周围很多同学觉得Java基础简单随手翻翻就过了。但实际上像HashMap为什么在JDK 8之后要引入红黑树、ConcurrentHashMap在JDK 8之后为什么废弃了分段锁改用CASsynchronized这些细节如果不深入源码层面去理解到了考场上真的会发慌。因为这些变化不是孤立的技术升级而是和并发场景下的性能瓶颈直接相关爱奇艺这种高并发场景下Redis缓存、Kafka生产者消费者、Spark任务调度到处都涉及并发编程所以考察这部分内容是完全合理的。2.2 Hadoop生态组件HDFS、MapReduce、YARNHadoop是很多大数据平台的底座虽然现在很多公司已经在用Spark和Flink做计算但HDFS作为分布式存储层的位置几乎是不可撼动的。笔试里HDFS相关的核心考点就那么几个NameNode和DataNode的角色分工、数据块副本机制和默认副本数、读写流程中的关键步骤、以及SecondaryNameNode到底做不做热备份这里是个经典误区它其实只做定期合并edit logs不能故障热切换。MapReduce虽然在实际生产中直接使用的频率在降低但作为理解分布式计算思想的“第一课”笔试依然经常考。重点包括Map阶段和Reduce阶段的shuffle过程、分区Partitioner的作用、Combiner能不能改变最终计算结果要注意使用场景、以及数据倾斜在MapReduce里怎么处理。这些底层的原理实际上直接延续到了Spark的Shuffle机制里你把这层纸捅破了后面学Spark会轻松很多。YARN的考点相对更偏资源调度比如ResourceManager和NodeManager的关系、Container的概念、以及一个Application的提交和运行流程。这块内容比较容易被忽略但它对应的是大数据集群的资源管理问题实际工作中排查任务失败、资源不足这类问题都需要对YARN有清晰认知。2.3 分布式计算引擎Spark为主Flink为辅2019年的秋招实时计算的市场基本已经是Flink的天下但离线计算仍然是以Spark为主力。所以这套B卷里Spark的内容占比很高Flink也开始出现。Spark的考察主要集中在几个方面一是RDD的特性和依赖关系窄依赖/宽依赖这是理解Spark任务划分的基础二是DAG的生成和Stage的划分逻辑这个几乎每年必考三是Shuffle过程的原理和优化四是Spark SQL的执行流程包括Catalyst优化器的作用五是Spark Streaming和Structured Streaming的区别。我在辅导同学的时候发现一个常见的盲区很多人能背出Spark的术语但不理解RDD的“血缘关系”和“容错”之间的关系。面试官只要追问一句“如果一个节点挂了Spark怎么恢复丢失的分区数据”很多人就卡住了。实际上RDD通过记录自身的依赖链条即血缘可以在某个分区数据丢失的时候从父RDD重新计算这就是Spark容错机制的核心思想。这部分虽然不会让你手写一个Spark任务那么直接但它是区分“真懂”和“背概念”的试金石。Flink在笔试里出现的题型更多是概念性对比比如Flink的窗口机制滚动窗口、滑动窗口、会话窗口、事件时间和处理时间的区别、Exactly-Once语义怎么实现、以及Checkpoint机制的基本流程。因为实时计算岗位通常单独招人大数据开发方向对Flink的要求一般到“理解并能简单使用”这个层面。但如果你的简历里写了熟悉Flink那么面试官就很可能往深了问这时候你就得能说清楚状态后端StateBackend、反压Backpressure这些进阶概念了。2.4 Hive与数仓建模从SQL到底层原理视频平台的数据分析需求极其旺盛运营要看PV/UV、播放时长分布、会员转化漏斗、内容热度排行等等这些报表数据绝大多数是从Hive数仓里来的。所以Hive的考察权重很高。平时大家写Hive SQL的时候感觉很爽像写普通SQL一样但笔试里会问一条Hive SQL是怎么一步一步变成MapReduce任务执行的这里面就涉及Hive的架构组件MetaStore元数据存储、Driver解析器、编译器、优化器、执行器以及和YARN的交互过程。如果你能画出来一条SQL从提交到返回结果的完整流程图这道题基本就稳了。数仓建模的考察通常是以场景题的形式出现比如“如果让你给爱奇艺的会员业务建一个数仓你会怎么分层”。参考答案一般要提到ODS层原始数据层、DWD层明细数据层、DWS层汇总数据层、ADS层应用数据层。每一层的作用不一样ODS就是原样接入业务数据不做太多加工DWD做清洗、脱敏、维度退化统一成明细宽表DWS按照主题做轻度汇总比如按天、按小时汇总用户维度的指标ADS直接面向业务方出报表或者接口数据。这套分层方法论在互联网公司基本是标配笔试里答出来面试官就觉得你确实有数仓项目的经验而不是只在LeetCode上刷了几道题。2.5 消息队列与缓存Kafka和Redis是高频配角Kafka在日志采集链路中扮演的角色太重要了。一套典型的离线数仓架构里业务服务器的日志先发送到KafkaKafka再作为数据源被Flume、Spark Streaming或者Flink消费最后落地到HDFS或者数仓里。所以笔试里Kafka几乎也是必考的。Kafka的考察点主要包括主题Topic和分区Partition的关系、分区内消息有序而分区间无法保证全局有序、生产者消息发送的三种确认机制acks0, 1, -1、消费者组Consumer Group的消费模式、以及Kafka怎么通过ISR机制保证消息不丢失和不重复。2019年这个时间点Kafka的事务消息和幂等生产者也开始出现在面试题里不过相对偏门。Redis在笔试里更多的是以缓存设计题的形式出现比如缓存穿透、缓存击穿、缓存雪崩的区别和解决方案。这三个概念看起来都是“缓存出问题了”但出问题的位置和应对策略完全不同。缓存穿透是查询了一个不存在的key导致请求直接打到数据库缓存击穿是某个热点key过期瞬间大量请求同时打到数据库缓存雪崩是大批key同时过期或者Redis宕机导致所有请求打到数据库。对应方案分别是布隆过滤器、互斥锁逻辑过期、加随机过期时间集群高可用。顺带还会考Redis的数据类型、过期策略、持久化方式RDB和AOF等基础问题。2.6 算法与数据结构不卷LeetCode但基础题要拿分大数据开发岗位的算法题整体难度不会像后端开发那么高一般集中在数组、链表、字符串、二叉树、排序、哈希表这些基础数据结构上。题目类型包括手写快排、二分查找、链表反转、括号匹配等等偶尔会出现一道中等难度的动态规划。为什么大数据开发也要考算法因为在大数据处理场景中你会频繁遇到数据去重、TopN统计、归并排序等场景。比如用堆来实现海量数据中的TopK问题就是MapReduce里常用思想的延伸。而且写算法题能直接看出候选人的代码能力和逻辑思维这是做任何开发工作的基本功。我的建议是把LeetCode热题100里的简单题和中等题刷一遍重点掌握数组、字符串、哈希表和二叉树这几类。大数据方向不需要死磕困难题性价比不高。但要注意笔试题里的算法题通常要求你写核心逻辑而不是像LeetCode那样光写个方法体有时候还会要求你分析时间和空间复杂度所以平时练习的时候不要只追求通过用例要把思路和复杂度分析一并想清楚。3. 从一道场景题看大数据的完整思维链条笔试题的压轴部分往往是场景设计题。我拿爱奇艺最典型的一个需求来做例子统计全网视频按天的播放量Top10榜单。这道题我觉得特别有代表性因为它没有标准答案但能看出一个候选人对整个大数据处理链路是否形成闭环思维。3.1 需求拆解先竖立正确的目标看到这个需求很多人第一反应是“那直接select xx from xxx group by xxx排序不就完了吗”如果你这么想说明你还没有建立起大数据开发的体系化思维。这个需求的关键词是“全网”这意味着数据体量巨大关键词是“Top10榜单”这意味着不仅要统计还要排序取前10关键词是“按天”这意味着是离线计算场景。正确的解题思路是要先明确这个榜单的统计口径是什么。比如播放量是指“播放请求次数”还是“实际播放时长超过多少秒才算一次有效播放”爱奇艺这种平台一定会定义严格的指标口径否则数据出来大家都是糊涂账。在实际笔试题里如果能把统计口径的假设说明白并且指出业务方需要和我们确认这种细节反而是加分项。3.2 数据从哪来设计采集和传输链路播放日志从用户客户端产生首先要经过一个埋点SDK上报到日志服务器然后日志服务器把数据发到Kafka。为什么中间要加一层Kafka因为日志服务器产生的数据是突发性的比如晚间高峰时段数据量会暴增如果不加缓冲下游直接写HDFS很容易被打垮。Kafka用它的分区机制来扛住高吞吐写入同时为下游多个消费者比如实时计算和离线计算各来一份提供了数据复用的可能。在笔试题里就要把这条链路写清楚客户端SDK - 日志服务器 - KafkaTopic: play_log根据视频ID或者用户ID进行分区 - Flume或者直接由Spark任务读取Kafka数据 - 落入HDFS的原始日志目录。这里面还要考虑为什么要进行分区如果按照视频ID进行分区那么同一个视频的日志会进到同一个分区这样在后续统计的时候消费端可以利用局部性优化并行度。3.3 数据怎么算离线计算流程设计落到HDFS的原始日志下一步要进入Hive数仓。首先是ODS层直接映射原始日志表表结构就是日志的原始字段。然后是DWD层做数据清洗比如过滤掉user_agent为空的记录、过滤掉播放时长小于5秒的记录防刷、处理时间字段的格式统一。接下来是DWS层按照“日期视频ID视频标题”的维度做聚合计算每个视频每天的播放次数和播放总时长这一步通常会产出一张按天分区的汇总表。最后在ADS层做Top10的榜单计算可以用SQL直接在DWS表上做排序但要考虑表的数据量。如果DWS表是亿级别的数据量在SQL里直接order by会触发全量排序性能堪忧。更合理的方式是先用SQL做一次Rank或者用Spark的窗口函数row_number()按播放量倒序排列并筛选rank 10这样能有效避免大表全排序。这里还有一个很实际的问题如果今天的原始日志量非常大比如好几TB用什么方式去加速处理如果只是纯Hive SQL默认的MapReduce引擎比较慢。这时候可以顺手提一句“用Spark on Hive来跑并设置动态分区和合理的并行度”甚至可以考虑用小文件合并和列式存储Parquet Snappy压缩来优化读取性能这些都能看出你对性能调优是有意识的。3.4 结果怎么用榜单数据的输出与可视化榜单算出来之后不是丢一个文件就结束了。通常是把结果表同步到MySQL或者直接用报表工具读取ADS层结果表生成可视化大屏。同步到MySQL的时候要注意数据量不大直接用Sqoop或者DataX每日增量同步就行如果希望数据实时性更强也可以把结果写回Redis供线上接口查询十分钟前的榜单变化。这个场景题其实就是在考察“端到端”的能力。你的回答里如果能把采集、存储、计算、调度、输出这个链条说清楚再在关键节点加上自己的性能调优和异常处理思路我觉得这道大题基本就满分了。4. 高频考点详解这些内容我建议你吃透前面说的是知识版图这里我再挑几个笔试中出现频率最高、也最能拉开分差的考点展开讲讲原理和实际处理思路这样你复习的时候也能更有方向感。4.1 数据倾斜大数据笔试的“钉子户”数据倾斜这个问题几乎在所有大数据相关的笔试面试里都会出现。它的本质是数据分布不均导致某个task处理的数据量远超其他task整个作业的运行时间被这个“最慢的长尾任务”拖住。在MapReduce和Spark里数据倾斜最常见的发生位置是Shuffle阶段比如group by的key分布不均、两张大表join时关联键大量重复、或者distinct计数时某个值特别多。笔试里一般会问你“遇到数据倾斜怎么办”其实答案是有套路的。第一先定位是哪一阶段出了问题看task的运行时长和shuffle读写数据量或者看Spark UI里某个stage的处理数据量是不是远超中位数。第二根据原因做针对性解决如果是join倾斜可以把热点key单独拆分加随机前缀再广播小表如果是group by倾斜可以先做局部聚合再加盐做二次聚合如果是空值导致的倾斜可以考虑给空值加随机后缀或者把空值过滤掉单独处理。第三排查数据源本身的字段质量比如视频ID为空、IP地址为空等等可能从源头就是脏数据。我在实际工作里遇到最多的情况其实就是空值和大key的问题。比如按照用户ID做统计时有一批测试账号或者游客账号数量特别大直接导致Reducer卡死。这类问题要在数仓的ODS或DWD层就做掉脏数据处理别等到下游引擎层面再临时解决。4.2 Hive SQL的优化思路Hive的题目除了问架构原理还会给出一段SQL让你分析和优化。常规的优化思路包括使用分区表和分桶表用小表join大表或者反过来在Spark里用broadcast join在join前提前过滤掉无关的数据减少shuffle的数据量避免SELECT *只取需要的字段以及合理设置reduce数量。另外一个比较隐蔽但高频的考点是数据文件格式的选择。面试官可能问你为什么推荐使用Parquet而不是纯文本格式答案的核心在于列式存储带来的好处查询时只读取需要的列减少I/O配合压缩算法可以获得很高的压缩比Parquet还内嵌了schema信息读数据时更安全。这个知识点在真实业务优化中非常常见因为数据量大的时候存储格式和压缩方案的选择直接影响成本和查询速度。4.3 Spark作业的基本调优Spark的调优是另一个重点。常考的方向包括内存模型堆内和堆外内存、执行内存和存储内存的划分、RDD的分区数设置、Shuffle Partitions的调整、使用Kryo序列化器减少内存占用、以及Spark动态资源分配Dynamic Allocation的原理。有一个点特别值得注意就是很多同学会不理解shuffle分区的数量和并行度之间的区别。Spark参数spark.sql.shuffle.partitions是在SQL操作join、group by、distinct时控制shuffle后生成多少个分区的默认是200个。如果数据量很小200个分区白白产生200个task调度开销很大如果数据量巨大200个分区又不一定够用。所以这个参数要结合数据量和集群资源来动态调整。在实际项目中我倾向于先跑一次小数据量验证逻辑再根据任务表现逐步调参而不是一上来就拍脑袋写个大的数字。另外广播变量Broadcast Variable和累加器Accumulator也是高频考点。广播变量是把一个只读的大变量复制到每个executor上避免每个task都传送一份副本累加器则是实现全局只增变量的机制常用于在driver端汇总各个task的运行指标。二者在源码层面都很有讲头笔试里至少要知道它们的使用场景和区别。4.4 Kafka的可靠性保证消息不丢失和不重复Kafka相关的题最后经常会落到两个核心问题上消息会不会丢消息会不会重复这其实对应的是分布式系统里的“At-Least-Once”、“At-Most-Once”和“Exactly-Once”三种投递语义。先说消息不丢要分三端来讨论。生产者端要设置acksall或者acks-1并且确保消息发送是同步等待回调或者使用事务APIBroker端要设置副本因子大于1并且min.insync.replicas要合理设置防止单点故障消费者端处理完业务逻辑再提交offset避免“消费了但没处理完就提交offset”导致的消息丢失。另外如果使用Flink作为消费者Flink的Checkpoint机制能保证状态和Kafka offset的一致性这是实现端到端Exactly-Once的基础。再说消息重复这主要出现在消费者端因为消费者拉取一批消息后在处理过程中崩溃了offset没有及时提交重启后就会重新消费这一批消息。解决方案要么是业务逻辑天然支持幂等比如写入数据库时用唯一键约束要么就是借助Kafka的幂等生产者加事务API在流处理框架里实现精确一次消费。笔试里能把这个链路分析清楚说明你真的用过Kafka在生产环境里踩过坑而不只是看过文档。5. 备考策略和实操心得聊完具体的知识点最后再来说说准备这套笔试以及类似的大数据开发笔试的整体策略。这些东西是我自己当初求职踩过坑后来带实习生也反复提醒过很多次的经验。5.1 三轮复习法从扫盲到真题到模拟第一轮是知识扫盲。把常用组件的基本概念、架构原理、使用场景过一遍确保没有知识盲区。这一轮最重要的是把“是什么”和“为什么”连起来比如不只是背“HDFS适合存大文件”还要想清楚它为什么不适合存大量小文件因为它每个文件的元数据都保存在NameNode内存里小文件太多会撑爆NameNode。第二轮是真题训练。找到往年的大数据笔试题按模块刷总结高频题型和答题套路。这里尤其要注重“简答题”和“场景题”的训练不能只看选择题和判断题。动笔写一遍和心里想一遍是完全不同的写出来的东西往往更能暴露你的逻辑漏洞。我当时准备的时候把Kafka的消费者组流程、HDFS的读写流程、Spark的Stage划分流程分别画成流程图反复默写直到闭上眼睛能完整复述出来。第三轮是模拟实战。自己给自己出一个综合性的场景题然后按照“端到端”的思路把采集、存储、计算、调度、分发这条链路完整写下来。甚至可以假设集群出现了某种故障比如NameNode宕机、某个节点磁盘写满、Kafka消费者积压严重你来写排查思路和解决方案。这种模拟训练能帮你在考场上面对灵活的大题时不慌不忙。5.2 题目要做完但更要留下好印象笔试的题量通常不小时间比较紧张。我的建议是先把简单的、会做的题目快速做掉拿到基础分遇到不会的题目宁可根据自己的理解写一点思路也不要留白。因为很多批改是人工看的你哪怕写得不对只要有思路也能看出你是有工程sense的。还有一个容易被忽略的细节字迹和排版。笔试如果是在线OK代码部分一定要缩进清晰、变量命名规范。这些细节看起来不影响对错但实际上很多阅卷官会通过这些细节来评估候选人的代码习惯。一个连变量名都乱写的人很难让人相信他在实际工作中能写出可维护的代码。5.3 简历项目和笔试内容的呼应如果笔试通过进入面试面试官一定会围绕你简历里的项目经历展开。所以准备的题目和知识点最好能和你简历上的项目做一个映射。比如公司笔试考了Flink的窗口机制你简历里恰好写了一个实时统计UV的项目那么面试的时候就要重点准备这个项目当时的窗口划分是怎么做的、状态都存了什么、出现故障后怎么恢复。项目不一定要多高大上但一定要是自己真正动手做过、能讲清楚细节的。5.4 心态调整笔试不是终点最后想说一下心态。很多同学把笔试看得很重一遇到不会的题就紧张后面会的题也发挥不好了。实际上大数据开发方向的笔试本来就不可能全做完也不会要求你全对。它的目的是在尽量短的时间里评估你的知识面和学习潜力。遇到不会的知识点坦然面对把会做的部分做到最好这本身就是一种能力。我在实际辅导中常跟同学讲平时多积累考试时稳得住这才是最关键的。你今天在这套题里暴露出来的漏洞恰恰是你接下来几天最需要补的课。每一次笔试都是宝贵的“体检报告”善用它你就离offer越来越近了。笔试题说到底是一面镜子照出来的是你平时学习的足迹。把基础挖深把链路打通把细节抠透你自然能在笔试中展现出真正的实力。希望这篇拆解能帮你理清思路在大数据开发这条路上走得更稳。