简介:本资源为《Spark编程基础及项目实践》配套期末试卷及答案2套,面向正在学习Spark与大数据技术的高校学生及自学者,用于检验核心概念掌握程度与考前自测。内容覆盖大数据四大特征、Scala变量与函数定义、RDD基本计算单元、GraphX图操作、MLlib特征选择、Spark内存管理与部署模式、Spark Streaming输入源及滑动窗口参数等知识点,题型包含单选、填空、简答与程序题,其中程序题要求用Scala完成单词统计的完整编码。资源共1个PDF文件,压缩包约199KB,排版清晰便于打印练习。目前已有2221人学习下载,适合需要系统梳理Spark知识框架、对照答案查漏补缺的读者使用。
1. 两份试卷能撑起一次 Spark 考前突击吗
上周有个做数据开发的朋友找我,说他们团队要内部考核 Spark,手头只有一份《Spark编程基础及项目实践》试卷及答案2套.pdf,问我这东西到底能不能当复习主线用。我拿到手翻了一遍,两套卷子覆盖了 RDD 算子、DataFrame、Spark SQL、Shuffle 机制、集群部署模式这些核心考点,题型以选择、填空、简答和代码补全为主,答案部分带解析。说白了,这不是什么项目源码包,而是一份面向课程考核的纸质资料电子化版本,适合正在学 Spark 编程基础、准备期末或面试笔试的人拿来查漏补缺。它解决的不是“怎么从零搭一个生产集群”,而是“我对 Spark 的知识点到底掌握到什么程度”。如果你已经跑过 wordcount、写过几个 transformation,但说不清宽窄依赖的区别,这份卷子能帮你把盲区逼出来。下面我按自己拆题的顺序,讲讲怎么把这两套卷子用出复现价值。
2. 拆解试卷考点分布:从 RDD 到 Spark SQL 的覆盖逻辑
2.1 先看两套卷子各自考了什么
我把两套卷子的题目按知识点做了归类,发现出题人明显是按“编程基础 + 项目实践”两条线走的。第一套偏基础,RDD 的 map、filter、flatMap、reduceByKey、groupByKey 反复出现,还有几道关于 lineage 和 checkpoint 的选择题。第二套往项目实践靠,出现了 Spark SQL 的 DataFrame 创建方式、DSL 与 SQL 两种写法对比、以及一个简答题问“如何处理数据倾斜”。这种分布其实很典型:先确认你懂算子语义,再确认你能把算子组合成业务逻辑。
从题型分值看,代码补全题占比不低,通常给一段 Scala 或 Python 代码,挖掉关键算子让你填。这类题最怕的是“看着会、写出来错”,比如 reduceByKey 和 groupByKey 在 shuffle 行为上的差异,卷子里用选择题和简答题各考了一遍。我的建议是,拿到卷子先别急着做,花二十分钟把每道题对应的知识点标在目录上,你会得到一张自己的薄弱点地图。
2.2 用考点反推复习优先级
归类之后我发现,Shuffle 相关题目在两套卷子里出现了至少五次,形式包括选择、简答和代码分析。这说明出题人认为 Shuffle 是 Spark 编程基础里最容易翻车的地方。事实也确实如此,很多初学者能写出 wordcount,但被问到“reduceByKey 和 groupByKey 谁更省内存”就卡住了。卷子里有一道题直接问“以下哪个操作会触发 shuffle”,选项里混了 map、filter、reduceByKey、coalesce,这种题就是用来筛掉只会背 API 的人。
另一个高频区是 Spark SQL 的日期函数。热搜里有人搜“spark sql 日期加 年”“spark sql 日期转存月份”,卷子里虽然没直接考这些函数名,但有一道 DataFrame 操作题需要按月份聚合,答案里用了 date_format 和 add_months。这说明复习时不能只背函数列表,得知道在什么业务场景下组合使用。我一般会建议把卷子里所有涉及“聚合”“分区”“序列化”的题目单独拎出来,这三类知识点在笔试和面试里复现率最高。
2.3 答案部分怎么用才不浪费
很多人对答案的态度是“做完对一下”,但这套卷子的答案带解析,价值在于解析里提到的边界条件。比如一道关于 mapPartitions 的题,解析里专门说了“每个分区一个迭代器,注意内存溢出风险”,这句话在教材里可能只是一行小字,但在实际写代码时就是血泪经验。我拆题时习惯把解析里出现的“注意”“但是”“如果”圈出来,这些词后面往往跟着踩坑点。
另外,答案里的代码片段可以直接拿来在本地 Spark 环境里跑一遍。比如卷子里有一道用 reduceByKey 做词频统计的补全题,答案给的是完整代码,你把它复制到 spark-shell 里,换一个文本文件就能验证。这种“试卷代码 → 本地复现”的路径,比单纯背答案有效得多。需要注意的是,卷子里的代码默认是 Scala 或 Python,如果你本地装的是 PySpark,语法要对应调整,别直接混用。
3. 把试卷代码跑起来:本地环境复现与算子验证
3.1 用 PySpark 复现卷子里的词频统计题
卷子里有一道经典题:给一段文本,用 Spark 统计每个单词出现的次数,要求用 reduceByKey 实现。答案给的是 Scala 版本,我把它转成 PySpark 在本地跑了一遍。先确认你本地有 Python 和 Java 环境,然后装 pyspark:
pip install pyspark==3.5.0版本不用严格一致,3.x 都能跑。接着写一个脚本,把卷子里的逻辑落地:
from pyspark import SparkContext, SparkConf # 本地模式,用两个线程模拟并行 conf = SparkConf().setMaster("local[2]").setAppName("WordCountExam") sc = SparkContext(conf=conf) # 模拟卷子里的输入文本 text = "spark hadoop spark sql hadoop spark" rdd = sc.parallelize(text.split(" ")) # 卷子要求:map 成 (word, 1) 再 reduceByKey result = rdd.map(lambda word: (word, 1)).reduceByKey(lambda a, b: a + b) print(result.collect()) sc.stop()这段代码的逻辑和卷子答案完全对应:parallelize 把本地集合转成 RDD,map 做映射,reduceByKey 按 key 聚合。参数上,setMaster("local[2]") 表示本地两线程,适合验证逻辑,不用搭集群。跑完你会看到 [('spark', 3), ('hadoop', 2), ('sql', 1)],和卷子答案一致。如果报错 “Java gateway process exited”,通常是 JAVA_HOME 没配好,这是本地跑 PySpark 最常见的翻车点。
3.2 验证宽窄依赖:从试卷选择题到实际 lineage
卷子里有一道选择题问“哪个操作会产生宽依赖”,选项有 map、filter、reduceByKey、union。答案是 reduceByKey。光知道答案不够,我一般会让学生用 toDebugString 把 lineage 打出来看:
# 接上面的 sc rdd2 = sc.parallelize([("a", 1), ("b", 2), ("a", 3)]) grouped = rdd2.groupByKey() reduced = rdd2.reduceByKey(lambda x, y: x + y) print("groupByKey lineage:") print(grouped.toDebugString().decode()) print("reduceByKey lineage:") print(reduced.toDebugString().decode())运行后你会看到 groupByKey 和 reduceByKey 的 lineage 里都出现了 ShuffledRDD,说明两者都触发 shuffle。但卷子解析里强调 reduceByKey 会在 map 端做本地聚合,而 groupByKey 不会。这个差异在数据量大时就是内存溢出的分水岭。参数上没什么可调的,关键是理解“map 端聚合”这个动作发生在 shuffle 之前。如果你在本地跑,数据量小看不出区别,可以造一个几十万条的列表再对比运行时间,差异会很明显。
3.3 用试卷里的 DataFrame 题练 Spark SQL 日期处理
第二套卷子有一道题要求按月份统计订单金额,答案用了 date_format。我把它扩展成可运行的 PySpark SQL:
from pyspark.sql import SparkSession from pyspark.sql.functions import col, date_format, sum spark = SparkSession.builder.master("local[2]").appName("DateExam").getOrCreate() # 模拟订单数据 data = [("2024-01-15", 100), ("2024-02-20", 200), ("2024-01-25", 150)] df = spark.createDataFrame(data, ["order_date", "amount"]) # 卷子考点:日期转月份并聚合 result = df.withColumn("month", date_format(col("order_date"), "yyyy-MM")) \ .groupBy("month").agg(sum("amount").alias("total")) result.show() spark.stop()这里 date_format 的第二个参数 "yyyy-MM" 就是卷子解析里提到的格式串,换成 "MM" 只取月份,换成 "yyyy" 取年份。热搜里有人搜“spark sql 日期加 年”,对应的是 add_months 或 date_add,卷子没直接考,但你可以用同样方式验证:df.withColumn("next_year", add_months(col("order_date"), 12))。参数说明:add_months 第二个参数是月数,正数往后加,负数往前减。这种从试卷考点延伸到实际函数的练法,比死记硬背强。
4. 避坑排查:做这套试卷时最容易翻车的五个地方
4.1 现象:代码补全题写对了算子,但顺序错了
原因:Spark 算子分 transformation 和 action,卷子里有些题故意把 action 放在 transformation 前面,比如先 count 再 map,逻辑上就跑不通。很多人只关注算子名,忽略了调用顺序。解决:做补全题时先判断整段代码的输入输出类型,RDD 转 RDD 是 transformation,RDD 转数值或列表是 action。把 action 留到最后一步。
4.2 现象:简答题写了很多,但没踩到得分点
原因:卷子答案的解析是按关键词给分的,比如问“Spark 为什么快”,得分点是“内存计算”“DAG 调度”“窄依赖优化”,你写一大段“因为不用磁盘”可能只拿一半分。解决:做简答题前先看分值,分值高的题通常有多个得分点,按点作答,每个点一句话说清。我一般会数答案里的分号或序号,那就是得分点数量。
4.3 现象:本地跑试卷代码报序列化错误
原因:PySpark 在集群模式下需要序列化函数,本地模式有时也会因为 lambda 里引用了外部不可序列化对象而报错。卷子里的代码通常是纯算子,但你自己扩展时容易引入。解决:把 lambda 里用到的外部变量改成字面量或广播变量。如果报 “PicklingError”,检查是不是在 map 里用了 self 或数据库连接。
4.4 现象:把 reduceByKey 和 groupByKey 的结果当成一样
原因:两者在结果上确实都能得到 (key, 聚合值),但 groupByKey 返回的是 (key, iterable),后续还得 map 一次。卷子里有题问“哪个更高效”,答案选 reduceByKey,但很多人做代码题时随手写了 groupByKey 也能跑通,就以为没区别。解决:记住 reduceByKey 有 map 端 combine,groupByKey 没有。数据量大时 groupByKey 会把所有 value 拉到同一个节点,内存直接爆掉。
4.5 现象:Spark SQL 日期函数返回 null
原因:date_format 要求输入是日期类型,如果你传的是字符串且格式不标准,解析失败就返回 null。卷子里给的日期都是标准格式,但实际数据里可能是 "2024/01/15"。解决:先用 to_date 显式转换,指定格式:to_date(col("order_date"), "yyyy/MM/dd")。这个坑在热搜“spark sql 日期转存月份”里也有人踩过,转换前先确认原始格式。
5. 从试卷到实战:用错题反推 Spark 集群搭建的盲区
做完两套卷子,你会发现有些题反复错,比如 Shuffle 调优、分区数设置、序列化选择。这些点如果只停留在试卷层面,下次遇到真实集群还是不会。我一般会挑三道错题,对应去本地或测试集群上验证一遍。比如卷子里问“spark.sql.shuffle.partitions 默认是多少”,答案是 200。你可以在 Spark SQL 里改这个参数看效果:
spark.conf.set("spark.sql.shuffle.partitions", "10")改完再跑一个 groupBy 聚合,观察 stage 里的 task 数量变化。默认 200 在小数据量下会启动 200 个 task,大部分空跑,浪费资源。这个参数在集群搭建时经常被忽略,但它是 Spark SQL 性能调优的第一刀。
另一个高频错点是 RDD 的 persist 和 cache。卷子里有一道选择题问“cache 默认存储级别是什么”,答案是 MEMORY_ONLY。但实际项目里,如果内存不够,MEMORY_ONLY 会导致分区被丢弃重算。我习惯在测试时用 MEMORY_AND_DISK,虽然慢一点但稳。你可以用试卷里的迭代计算题来验证:对一个 RDD 反复 count,分别在不 cache、cache、persist 三种情况下跑,看运行时间差异。这种验证比背答案直观得多。
最后说一个我自己的习惯:每次做完一套卷子,我会把错题对应的知识点写成一段可运行的代码,存到一个 exam_review 目录里。下次复习先跑代码,再看卷子。这套《Spark编程基础及项目实践》试卷及答案2套.pdf 的价值不在于题目本身,而在于它逼你把散落的算子、参数、机制串成一条线。如果你手头正好有这份资料,建议先做第一套,把错题标出来,再用第二套验证是否真的补上了。从那以后我每次带新人,都强制他们先做一遍这套卷子里的代码补全题,再上集群。希望帮到你。
本文还有配套的精品资源,点击获取