spark RDD的5个重要内部属性

RDDs 接口的五个属性
下表总结了 RDDs 的五个属性:

上述属性可以概括为几个方面:一组分区,表示数据集包含的分片;一组依赖关系,指向其父 RDD;一个函数,基于父 RDD 进行计算;以及划分策略和数据位置相关的元数据。

例如上文中的代码实例里,HDFS 文件作为输入,初始 RDD 的 partitions 代表文件中每个文件块的分区(包含文件块在每个分区对象中的偏移量),preferredLocations 表示文件块所在的节点,而 iterator 可以用来读取这些文件块。在一个 RDD 上调用 map 操作时,会返回一个 MappedRDD 对象,这个对象与其父对象具有相同的分区以及 preferredLocations,但在其 iterator 中,传递给 map 的匿名函数会应用到父对象中的数据。

RDDs 依赖关系
在 Spark 中,RDD 之间的依赖关系分为两类:

1.窄依赖:每个父 RDD 的分区都至多被一个子 RDD 的分区使用,即为 OneToOneDependecies;
2.宽依赖:多个子 RDD 的分区依赖一个父 RDD 的分区,即为 OneToManyDependecies。

例如,map 操作是一种窄依赖,而 join 操作是一种宽依赖(除非父 RDDs 已经基于 Hash 策略被精心划分过了)。

窄依赖和宽依赖的区别在 Spark 开发中很重要。

首先,窄依赖允许在单个集群节点上对一个数据分片进行流水线式操作,这个节点可以直接访问所有依赖的父级分区。例如,可以逐个元素地依次执行 filter 操作和 map 操作。相反,宽依赖需要所有的父 RDD 数据可用,并且数据已经通过类 MapReduce 中的 shuffle 操作完成了聚合。

其次,在窄依赖中,节点失败后的恢复更加高效。因为只有直接依赖的父级分区需要重新计算,并且这些父级分区可以并行地在不同节点上重新计算。相反,在宽依赖的继承关系中,单个失败的节点可能导致一个 RDD 的所有祖先 RDD 重算,从而导致大量计算的重新执行。不过,进行宽依赖类的操作(比如 shuffle 依赖)时,Spark 会将中间结果保存到父分区所在的节点上。这和 MapReduce 本地保存 Map 的输出类似,能简化数据的故障恢复过程。

检查点支持 (Checkpoint)
虽然 lineage 可用于出现错误后 RDD 的恢复,但对于 lineage 很长的 RDD 来说,从源头恢复耗时可能较长。因此,将某些 RDD 进行检查点操作 (Checkpoint),使之保存到稳定的存储上,对错误情况下的 RDD 重算是有帮助的。

通常情况下,对于包含宽依赖的长血统 RDD 设置检查点操作是非常有用的,因为宽依赖条件下,此类 RDD 失效会使得 Spark 从各个父 RDD 上重新取得数据进行恢复,且节点失效很有可能影响到宽依赖 RDD 的父节点,重算开销较大。相反,对于那些窄依赖于稳定存储上数据的 RDD 来说,对其进行检查点操作就不是很有必要,如果一个节点发生故障,RDD 在该节点中丢失的分区数据可以通过并行的方式从其他节点中重新计算出来,计算成本只是整个 RDD 的很小一部分。

Spark 当前提供了为 RDD 设置检查点(用一个 REPLICATE 标志来持久化)操作的 API,让用户自行决定需要为哪些数据设置检查点操作。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章