文章目录
- 1.什么是 RDD ?
- 2.RDD 的五大属性是啥
- 3.说一些常用的 RDD 算子
- 4.你知道 map 和 mapPartitions 有啥区别吗
- 5.reduceByKey 和 groupByKey
- 6. reduceByKey、foldByKey、aggregateByKey、combineByKey 区别
- 7.RDD 的宽窄依赖
- 8.RDD的缺点
- 9.DAG
- 10. spark 中 job,stage,task
- 11.Spark 广播变量和累加器
- 12.Spark 实现 TopN 的获取
1.什么是 RDD ?
RDD 就是弹性分布式数据集,可以理解为一种数据结构,拥有多种不同的 RDD 算子,从物理存储上看,一个数据集可能被分为多个分区,各个分区都有可能存放在不同的存储/计算节点上,而 RDD 则是在该数据集上的一个抽象,代表了整个数据集,但这个 RDD 并不会从物理上将数据放在一起。
有了 RDD 这个抽象,用户可以从一个入口方便的操作一个分布式的数据集。
2.RDD 的五大属性是啥
这里借用网上一张讲的很清晰的图来说明 RDD,如下图:
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。这样做的好处在于,在转换操作时就已经对数据进行了一次聚合操作,从而减小数据传输。如下图所示:
groupByKey 算子操作发生在动作操作端,即 Shuffle 之后,所以势必会将所有的数据通过网络进行传输,造成不必要的浪费。同时如果数据量十分大,可能还会造成 OutOfMemoryError。如下图所示:
6. reduceByKey、foldByKey、aggregateByKey、combineByKey 区别
reduceByKey 没有初始值 分区内和分区间逻辑相同
foldByKey 有初始值 分区内和分区间逻辑相同
aggregateByKey 有初始值 分区内和分区间逻辑可以不同
combineByKey 初始值可以变化结构 分区内和分区间逻辑不同
7.RDD 的宽窄依赖
一个作业从开始到结束的计算过程中产生了多个 RDD,RDD 之间是彼此相互依赖的,这种父子依赖的关系称之为“血统”。
- 如果父 RDD 的每个分区最多只能被子 RDD 的一个分区使用,称之为窄依赖(一对一)。
- 若一个父 RDD 的每个分区可以被子 RDD 的多个分区使用,称之为宽依赖(一对多)。
8.RDD的缺点
不支持细粒度的写和更新操作(如网络爬虫), spark 写数据是粗粒度的
所谓粗粒度,就是批量写入数据,为了提高效率。但是读数据是细粒度的也就是 说可以一条条的读。
不支持增量迭代计算, Flink支持。
9.DAG
DAG(Directed Acyclic Graph 有向无环图)指的是数据转换执行的过程,有方向,无闭环(其实就是 RDD 执行的流程);
原始的 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:广播变量用来把变量在所有节点的内存之间进行共享,在每个机器上缓存一个只读的变量,而不是为机器上的每个任务都生成一个副本。
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 的排序算子进行排序。