文章目录

1.什么是 RDD ?

RDD 就是弹性分布式数据集,可以理解为一种数据结构,拥有多种不同的 RDD 算子,从物理存储上看,一个数据集可能被分为多个分区,各个分区都有可能存放在不同的存储/计算节点上,而 RDD 则是在该数据集上的一个抽象,代表了整个数据集,但这个 RDD 并不会从物理上将数据放在一起。

有了 RDD 这个抽象,用户可以从一个入口方便的操作一个分布式的数据集。

2.RDD 的五大属性是啥

这里借用网上一张讲的很清晰的图来说明 RDD,如下图:

Spark Core_面试题_数据集
1.一组分区 :一组分片(Partition)/一个分区(Partition)列表,即是数据集的基本组成单位,标记数据在哪个区。

2.一个计算每个分区的函数 :一个函数会被作用在每一个分区。Spark 中 RDD 的计算是以分片为单位的,compute 函数会被作用到每个分区上。

3.RDD 之间的依赖关系 :一个 RDD 会依赖于其他多个 RDD。RDD 的每次转换都会生成一个新的 RDD,所以 RDD 之间就会形成类似于流水线一样的前后依赖关系。在部分分区数据丢失时,Spark 可以通过这个依赖关系重新计算丢失的分区数据,而不是对 RDD 的所有分区进行重新计算。(Spark 的容错机制)

4.一个 Partition :可选项,对于 KV 类型的 RDD 会有一个 Partitioner,即 RDD 的分区函数,默认为 HashPartitioner。

5.一个列表:可选项,存储存取每个 Partition 的优先位置(preferred location)。对于一个 HDFS 文件来说,这个列表保存的就是每个 Partition 所在的块的位置。

3.说一些常用的 RDD 算子

一种转换 transformation 操作、一种动作 action 操作

1.Map、MapPartitions、FlatMap、Filter、distinct、sortBy、union、reduceByKey、groupByKey、sortByKey、join

2.reduce、collect、count、save、take、aggregate、countByKey等。

4.你知道 map 和 mapPartitions 有啥区别吗

map:每次对 RDD 中的每一个元素进行操作;
mapPartitions:每次对 RDD 中的每一个分区的迭代器进行操作;

mapPartitions会造成OOM,内存溢出

5.reduceByKey 和 groupByKey

reduceByKey()会在 shuffle 之前对数据进行合并。有点类似于在 MapReduce 中的 combiner。这样做的好处在于,在转换操作时就已经对数据进行了一次聚合操作,从而减小数据传输。如下图所示:

Spark Core_面试题_spark_02
groupByKey 算子操作发生在动作操作端,即 Shuffle 之后,所以势必会将所有的数据通过网络进行传输,造成不必要的浪费。同时如果数据量十分大,可能还会造成 OutOfMemoryError。如下图所示:

Spark Core_面试题_数据_03

6. reduceByKey、foldByKey、aggregateByKey、combineByKey 区别

reduceByKey 没有初始值 分区内和分区间逻辑相同

foldByKey 有初始值 分区内和分区间逻辑相同

aggregateByKey 有初始值 分区内和分区间逻辑可以不同

combineByKey 初始值可以变化结构 分区内和分区间逻辑不同

7.RDD 的宽窄依赖

Spark Core_面试题_spark_04
一个作业从开始到结束的计算过程中产生了多个 RDD,RDD 之间是彼此相互依赖的,这种父子依赖的关系称之为“血统”。

  • 如果父 RDD 的每个分区最多只能被子 RDD 的一个分区使用,称之为窄依赖(一对一)。
  • 若一个父 RDD 的每个分区可以被子 RDD 的多个分区使用,称之为宽依赖(一对多)。

8.RDD的缺点

不支持细粒度的写和更新操作(如网络爬虫), spark 写数据是粗粒度的
所谓粗粒度,就是批量写入数据,为了提高效率。但是读数据是细粒度的也就是 说可以一条条的读。

不支持增量迭代计算, Flink支持。

9.DAG

DAG(Directed Acyclic Graph 有向无环图)指的是数据转换执行的过程,有方向,无闭环(其实就是 RDD 执行的流程);

Spark Core_面试题_大数据_05
原始的 RDD 通过一系列的转换操作就形成了 DAG 有向无环图,任务执行时,可以按照 DAG 的描述,执行真正的计算(数据被操作的一个过程)。

DAG 的边界

  • 开始:通过 SparkContext 创建的 RDD;
  • 结束:触发 Action,一旦触发 Action 就形成了一个完整的 DAG。

10. spark 中 job,stage,task

Job 简单讲就是提交给 spark 的任务。

Stage 是每一个 job 处理过程要分为的几个阶段。

task 是每一个 job 处理过程要分为几次任务。Task 是任务运行的最小单位。最终是要以 task 为单位运行在 executor 中。

11.Spark 广播变量和累加器

在默认情况下,当 Spark 在集群的多个不同节点的多个任务上并行运行一个函数时,它会把函数中涉及到的每个变量,在每个任务上都生成一个副本。但是,有时候需要在多个任务之间共享变量,或者在任务(Task)和任务控制节点(Driver Program)之间共享变量。

为了满足这种需求,Spark 提供了两种类型的变量:

  • 累加器 accumulators:累加器支持在所有不同节点之间进行累加计算(比如计数或者求和)。
  • 广播变量 broadcast variables:广播变量用来把变量在所有节点的内存之间进行共享,在每个机器上缓存一个只读的变量,而不是为机器上的每个任务都生成一个副本。

Spark Core_面试题_spark_06

12.Spark 实现 TopN 的获取

方法1:

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

方法2:

(1)取出所有的 key;(2)对 key 进行迭代,每次取出一个 key 利用 spark 的排序算子进行排序。

方法3:

(1)自定义分区器,按照 key 进行分区,使不同的 key 进到不同的分区;(2)对每个分区运用 spark 的排序算子进行排序。