4、RDD 弹性分布式数据集
4-1、RDD的基本概念
弹性分布式数据集,本质上就是特殊的只读的分区记录集合,可以分成多个分区,每个分区就是一个数据集片段,分区可以保存在不同节点上进行计算。
4-2、RDD的特点
- a list of partitions:一个RDD是由多个partition组成的list,一般情况下,一个partition对应HDFS的一个block也就是一个文件
- a function for partiotioner:一个函数作用在每一个分区上,比如map的函数,每个分区都会执行一遍
- A list of dependencies on other RDDs:RDD之间有血缘依赖,可以分为窄依赖和宽依赖
- Optionally, a Partitioner for key-value RDDs (e.g. to say that the RDD is hash-partitioned):RDD内存的数据是key-value类型的,也就是说可以根据key进行重新hash分区
- Optionally, a list of preferred locations to compute each split on (e.g.block locations for an HDFS file):RDD具有数据本地性,也就是尽量靠近数据,(数据不动,代码动)
4-3、RDD的依赖关系
RDD的依赖关系可以分为窄依赖和宽依赖
- 窄依赖:一个父RDD的分区只能对应一个子RDD的分区
- 宽依赖:一个父RDD的分区可以对应多个RDD的多个分区
宽依赖一般会伴随shuffle操作
宽窄依赖使得RDD有天生的容错性,并且窄依赖的恢复效率更高。
4-5、RDD的算子
RDD的算子可以分为Transformation算子和Action算子,其中Transformation算子时延迟计算的,只有遇到Action算子才会触发运算,Action算子会触发SparkContext 提交 Job 作业,进行计算。
Transformation算子如下:
算子名称 | 算子含义 |
---|---|
map(func) | 对RDD的每一条数据进行Map操作,最后返回新的RDD |
filter(func) | 对RDD的每一条数据进行过滤,最后返回符合条件的新的RDD |
flatMap(func) | 对RDD的每一条数据进行平铺Map操作,最后返回新的RDD |
mapPartitions(func) | 对RDD的每一个分区进行操作,与Map区别在于它是一次加载分区的所有数据进行Map操作,每个分区只执行一次func,性能较高,但是对内存要去较高,最后与Map操作数据一致,最后返回新的RDD。 |
union(other rdd) | 两个RDD进行并集操作,最后返回新的RDD |
intersection(other rdd) | 两个RDD进行交集操作,最后返回新的RDD |
distinct() | 对RDD进行去重,最后返回新的RDD |
groupByKey() | 对RDD根据key进行分组,返回新的RDD,类型为(K, Iterator[V])的RDD,会产生shuffle |
reduceByKey(func) | 对RDD根据key进行分组聚合操作,返回新的RDD,会产生shuffle |
sortByKey() | 对RDD根据key进行排序,返回新的有序的RDD,会产生shuffle |
sortBy(func) | 对RDD进行排序,可以自定义排序规则,返回新的有序的RDD,会产生shuffle |
join(other rdd) | 两个RDD做连接,返回相同的key的RDD,格式为(K,(V,W)) |
repartition() | 对RDD进行重分区操作,返回重分区后的RDD,会产生shuffle |
cache() | 缓存当前的RDD到内存中,如果内存不够则只缓存一部分,当后续再调用时,不需要根据血缘从源头计算,类似于检查点 |
persist() | 存储当前的RDD,与cache不一样的是,persist有多种存储策略,cache只是缓存到内存中,是persist的一种。 |
shuffle操作是进行重新分布数据的操作,这个过程需要大量读写磁盘,耗时相对较长,因此要尽量避免shuffle操作,如果避免不了,尽量采用更优的shuffle操作。
groupByKey()与reduceByKey(func)的区别:groupByKey()后面一般会跟上对数据操作的算子,比如map或filter,groupByKey()会直接将数据进行shuffle然后再操作,而reduceByKey会先在map阶段也就是节点本地先进行数据的combine合并可以自定义合并方式,这样就会减少shuffle数据传输的文件大小,性能更优。
groupByKey的示例图如下:
reduceByKey的示例图如下:
可以看出reduceByKey会在节点本地也就是shuffle前进行combine合并,这样在shuffle数据传输时,减少传输的文件,效率更高,因此,能用reduceByKey代替groupBykey就尽量代替,必须用的话就只能用groupByKey了。
Action算子如下:
算子名称 | 算子含义 |
---|---|
reduce(func) | 对RDD的所有数据进行自定义聚合操作,返回结果 |
collect() | 以数组的形式返回当前RDD的所有元素 |
first() | 返回当前RDD的第一个元素 |
take(n) | 返回当前RDD的前n个元素 |
aggregate() | 将RDD的所有数据进行相加,返回结果 |
foreach(func) | 分别对RDD的每一个元素进行操作,没有返回值 |
foreachPartition(func) | 分别对每一个分区进行操作,分区内还是对每一条数据进行操作,没有返回值 |
saveAsTextFile(path) | 将每个元素通过toString转成文本保存在文本文件中 |
saveAsSequenceFile() | 将RDD的元素以SequenceFile格式保存在文件中,对于HDFS,默认采用SequenceFile保存。 |
saveAsObjectFile() | 将RDD的元素序列化后保存到文件中 |