RDD的依赖关系
RDD和它依赖的父RDD的关系有两种不同的类型,即窄依赖(narrow dependency)和宽依赖(wide dependency)。
窄依赖:
窄依赖指的是每一个父RDD的Partition最多被子RDD的一个Partition使用(子rdd当中一个分去里面的数据来源于父rdd当中一个分区。叫做窄依赖。实际上没有产生shuffle过程)
宽依赖
宽依赖指的是多个子RDD的Partition会依赖同一个父RDD的Partition(子rdd当中一个分区里面的数据来源于父rdd当中好几个分区。实际上就是产生了shuffle,叫做宽依赖。)
对比图如下:
如何划分宽窄依赖:有没有产生shuffle过程
血统lineage:RDD只支持粗粒度转换,即只记录单个块上执行的单个操作。将创建RDD的一系列Lineage(即血统)记录下来,以便恢复丢失的分区。RDD的Lineage会记录RDD的元数据信息和转换行为,当该RDD的部分分区数据丢失时,它可以根据这些信息来重新运算和恢复丢失的数据分区。根据rdd之间的依赖关系,将依赖关系给记录下的血统。血统的记录可以帮助我们做容错。
例如:
rdd1 ==> rdd2 ==> rdd3 ==> rdd4
记录下来每一个rdd的父rdd是谁,也记录下来每一个rdd的子rdd是谁
可以帮助我们做容错
rdd3数据丢失:rdd2.map =rdd3
RDD的缓存
Spark速度非常快的原因之一,就是在不同操作中可以在内存中持久化或者缓存数据集。当持久化某个RDD后,每一个节点都将把计算分区结果保存在内存中,对此RDD或衍生出的RDD进行的其他动作中重用。这使得后续的动作变得更加迅速。RDD相关的持久化和缓存,是Spark最重要的特征之一。可以说,缓存是Spark构建迭代式算法和快速交互式查询的关键。
RDD缓存方式:
主要有两种,cache方法和persist方法但是并不是这两个方法被调用时立即缓存,而是触发后面的action时,该RDD将会被缓存在计算节点的内存中,并供后面重用。
查看 StorageLevel 类的源码来获取缓存的级别:
object StorageLevel {
val NONE = new StorageLevel(false, false, false, false) 不缓存
val DISK_ONLY = new StorageLevel(true, false, false, false) 存在一个硬盘上
val DISK_ONLY_2 = new StorageLevel(true, false, false, false, 2) 存两个硬盘上
val MEMORY_ONLY = new StorageLevel(false, true