面试过程中经常会遇到一个问题:谈谈你对Spark RDD的理解,你该如何回答呢?RDD是弹性数据集,是Spark的基础数据结构,然后呢,没了吗?那我觉得可能面试官觉得你应该处于最低级的水平,本文详细的介绍了RDD,面试过程中你如果按照下面的顺序进行描述RDD,面试官应该会对你刮目相看。
概述
RDD是(Resilient Distributed Dataset)弹性分布式数据集,Spark中数据的基本抽象,表示不可变的,分区的可以并行操作的元素集合。RDD有五大部分组成:
- 分区集合: partitions
- 每个分区的计算函数:compute
- 依赖关系: RDD依赖的RDDs
- 分区器: Partitioner分区器,只针对k-v RDD才会需要
- 最佳数据位置: 每个分区的最佳位置
五大要素
partitions
RDD由很多partition构成,在spark中,有多少partition就对应有多少个task。partition是逻辑概念,代表了一个split的数据,而不是包含或持有一个分片的数据,真正直接持有数据的是各个partition对应的迭代器,partition 对应的迭代器访问数据时也不是把整个分区的数据全量加载进行计算,而是像常见的迭代器一样一条条处理。
protected def getPartitions: Array[Partition]
那么会划分多少个分区,这个是由什么决定的?我们要分情况而定,可以分为从外界数据源读取数据,中间shuffle过程。
外界数据读取
Spark从HDFS读取数据时候,会根据文件文件格式InputFormat
和文件大小进行切分,切分成多个split,每个split可以组成一个partition,切分文件的个数取决于以下几个参数:
- 一个文件分片最小的有效字节数:
mapreduce.input.fileinputformat.split.minsize
- 一个文件分片最大有效字节数:
mapreduce.input.fileinputformat.split.maxsize
- HDFS中块的大小:
dfs.blocksize
这三个参数按照公式splitSize = max(minimumSize, min(maximumSize, blockSize))
来进行分片大小的确定,可以通过改变上述三个参数来调节最终的分片大小,详细的切分过程可以参考hadoop源码分析之文件拆分。
Shuffle过程
Shuffle过程中会根据分区器来进行分区数目的确定,默认使用HashPartitioner
,如果依赖的父RDD指定了分区器,则使用分区数目最大的分区器;否则会先看是否指定了spark.default.parallelism
,指定了根据这个指定的并行度来初始化HashParitioner
,否则使用依赖的rdd的最大分区数目来初始化HashParitioner
。