Spark 大厂面试题

9,934 阅读3分钟

这是我参与更文挑战的第29天,活动详情查看:更文挑战

一 Kryo序列化

Kryo序列化比Java序列化更快更紧凑,但Spark默认的序列化是Java序列化并不是Spark序列化,因为Spark并不支持所有序列化类型,而且每次使用都必须进行注册。注册只针对于RDD。在DataFrames和DataSet当中自动实现了Kryo序列化。

二 Spark中的血缘(笔试重点)

宽依赖和窄依赖。有Shuffle的是宽依赖。

三 Spark任务的划分

  1. Application:初始化一个SparkContext即生成一个Application;
  2. Job:一个Action算子就会生成一个Job;
  3. Stage:Stage等于宽依赖的个数加1;
  4. Task:一个Stage阶段中,最后一个RDD的分区个数就是Task的个数。

四 cache缓存级别

DataFrame的cache默认采用 MEMORY_AND_DISK
RDD 的cache默认方式采用MEMORY_ONLY

五 释放缓存和缓存

  1. 缓存:

    1. dataFrame.cache
    2. sparkSession.catalog.cacheTable(“tableName”)
  2. 释放缓存:

    1. dataFrame.unpersist
    2. sparkSession.catalog.uncacheTable(“tableName”)

六 缓存和检查点区别

  1. Cache缓存只是将数据保存起来,不切断血缘依赖。Checkpoint检查点切断血缘依赖。

  2. Cache缓存的数据通常存储在磁盘、内存等地方,可靠性低。Checkpoint的数据通常存储在HDFS等容错、高可用的文件系统,可靠性高。

  3. 建议对checkpoint()的RDD使用Cache缓存,这样checkpoint的job只需从Cache缓存中读取数据即可,否则需要再从头计算一次RDD。

七 Spark分区

  1. 默认采用Hash分区
    缺点:可能导致每个分区中数据量的不均匀,极端情况下会导致某些分区拥有RDD的全部数据。

  2. Ranger分区
    要求RDD中的KEY类型必须可以排序。

  3. 自定义分区
    根据需求,自定义分区。

请列举会引起Shuffle过程的Spark算子,并简述功能。 reduceBykey: groupByKey: …ByKey:

八 当Spark涉及到数据库的操作时,如何减少Spark运行中的数据库连接数?

使用foreachPartition代替foreach,在foreachPartition内获取数据库的连接。

九 如何使用Spark实现TopN的获取(描述思路或使用伪代码)(重点)

方法1:
1. 按照key对数据进行聚合(groupByKey)
2. 将value转换为数组,利用scala的sortBy或者sortWith进行排序(mapValues)数据量太大,会OOM。

方法2:
1. 取出所有的key
2. 对key进行迭代,每次取出一个key利用spark的排序算子进行排序

方法3:
1. 自定义分区器,按照key进行分区,使不同的key进到不同的分区
2. 对每个分区运用spark的排序算子进行排序

十 京东:调优之前与调优之后性能的详细对比(例如调整map个数,map个数之前多少、之后多少,有什么提升)

这里举个例子。比如我们有几百个文件,会有几百个map出现,读取之后进行join操作,会非常的慢。这个时候我们可以进行coalesce操作,比如240个map,我们合成60个map,也就是窄依赖。这样再shuffle,过程产生的文件数会大大减少。提高join的时间性能。

十一 Spark Shuffle默认并行度

参数spark.sql.shuffle.partitions 决定 默认并行度200