概念 | 概念理解和解释 | 备注 |
窄依赖 | 窄依赖指1个父RDD分区数据只被1个子RDD的分区使用,即一对一或多对一的关系。 分为两种映射情况:一个父RDD的分区对应于一个子RDD的分区,或者多个父RDD的分区对应于一个子RDD的分区。 1个子RDD的分区对应于1个父RDD的分区,比如map,filter,union等算子 1个子RDD的分区对应于N个父RDD的分区,比如co-partioned join | 两个或者固定几个part合到一个part,起到减少分区的作用,这个也是窄依赖,比如coalese。(coalese有参数可是设置shuffle使其从窄依赖变成宽依赖) |
宽依赖 | 宽依赖是指1个父RDD分区数据被多个子RDD分区使用,即一对多或多对多的关系。 宽依赖有分为两种情况 1个父RDD对应非全部多个子RDD分区,比如groupByKey,reduceByKey,sortByKey 1个父RDD对应所有子RDD分区,比如未经协同划分的join | RDD之间的依赖关系分为宽依赖、窄依赖。 Repartition 是宽依赖。 |
为什么要理解spark的宽依赖、窄依赖这个概念? | 1 窄依赖(narrow dependency) 可以支持在同一个集群Executor上,以pipeline管道形式顺序执行多条命令,例如在执行了map后,紧接着执行filter。分区内的计算收敛,不需要依赖所有分区的数据,可以并行地在不同节点进行计算。所以它的失败回复也更有效,因为它只需要重新计算丢失的parent partition即可 2 宽依赖(shuffle dependency) 则需要所有的父分区都是可用的,必须等RDD的parent partition数据全部ready之后才能开始计算,可能还需要调用类似MapReduce之类的操作进行跨节点传递。从失败恢复的角度看,shuffle dependency牵涉RDD各级的多个parent partition。 | 窄依赖,如果一个part失败了,只需要固定几个父part重跑,宽的就需要所有的都重跑了 |
有向无环图 | RDD之间的依赖关系形成DAG。 在Spark作业调度系统中,调度的前提是判断多个作业任务的依赖关系,这些作业任务之间可能存在因果的依赖关系,也就是说有些任务必须先获得执行,然后相关的依赖任务才能执行,但是任务之间显然不应出现任何直接或间接的循环依赖关系,所以本质上这种关系适合用DAG表示 | |
stage划分 | 由于shuffle依赖必须等RDD的父RDD分区数据全部可读之后才能开始计算,因此Spark的设计是让父RDD将结果写在本地,完全写完之后,通知后面的RDD。后面的RDD则首先去读之前RDD的本地数据作为输入,然后进行运算。 由于上述特性,讲shuffle依赖就必须分为两个阶段(stage)去做: (1)第1个阶段(stage)需要把结果shuffle到本地,例如reduceByKey,首先要聚合某个key的所有记录,才能进行下一步的reduce计算,这个汇聚的过程就是shuffle。 (2) 第二个阶段(stage)则读入数据进行处理。 为什么要写在本地? 后面的RDD多个分区都要去读这个信息,如果放到内存,假如出现数据丢失,后面所有的步骤全部不能进行,违背了之前所说的需要父RDD分区数据全部ready的原则。 同一个stage里面的task是可以并发执行的,下一个stage要等前一个stage ready(和map reduce的reduce需要等map过程ready一脉相承)。 |
|