内容简介:指父RDD的每一个分区最多被一个子RDD的分区所用,表现为一个父RDD的分区对应于一个子RDD的分区,和两个父RDD的分区对应于一个子RDD 的分区。图中,map/filter和union属于第一类,对输入进行协同划分(co-partitioned)的join属于第二类。指子RDD的分区依赖于父RDD的所有分区,这是因为shuffle类操作,如图中的groupByKey和未经协同划分的join。DAG,有向无环图,Directed Acyclic Graph的缩写,常用于建模。Spark中使用DAG对RDD
指父RDD的每一个分区最多被一个子RDD的分区所用,表现为一个父RDD的分区对应于一个子RDD的分区,和两个父RDD的分区对应于一个子RDD 的分区。图中,map/filter和union属于第一类,对输入进行协同划分(co-partitioned)的join属于第二类。
宽依赖:
指子RDD的分区依赖于父RDD的所有分区,这是因为shuffle类操作,如图中的groupByKey和未经协同划分的join。
DAG
DAG,有向无环图,Directed Acyclic Graph的缩写,常用于建模。Spark中使用DAG对RDD的关系进行建模,描述了RDD的依赖关系,这种关系也被称之为lineage,RDD的依赖关系使用Dependency维护,参考Spark RDD之Dependency,DAG在Spark中的对应的实现为DAGScheduler。
Stage
在spark中,会根据RDD之间的依赖关系将DAG图划分为不同的阶段,一个Job会被拆分为多组TaskSet,每组任务被称为一个Stage。对于窄依赖,由于partition依赖关系的确定性,partition的转换处理就可以在同一个线程里完成,窄依赖就被spark划分到同一个stage中,而对于宽依赖,只能等父RDD shuffle处理完成后,下一个stage才能开始接下来的计算。
Stage划分思路
-
因此spark划分stage的整体思路是:从后往前推,遇到宽依赖就断开,划分为一个stage;遇到窄依赖就将这个RDD加入该stage中。因此在上图中RDD C,RDD D,RDD E,RDDF被构建在一个stage中,RDD A被构建在一个单独的Stage中,而RDD B和RDD G又被构建在同一个stage中。
-
在spark中,Task的类型分为2种:ShuffleMapTask和ResultTask;
- ResultTask:对于 DAG 图中最后一个 Stage(也就是 ResultStage),会生成与该 DAG 图中哦最后一个 RDD (DAG 图中最后边)partition 个数相同的 ResultTask
- ShuffleMapTask:对于非最后的 Stage(也就是 ShuffleMapStage),会生成与该 Stage 最后的 RDD partition 个数相同的 ShuffleMapTask
-
每个Stage里面的Task的数量是由该Stage中最后一个RDD的Partition的数量所决定的
注意:同一个Stage的执行是串行的,比如Stage2的RDD C-D-F中,假设只有一个CPU core ,Spark是先将一条数据按C-D-F的顺序执行完后,再运行下一条数据。而不是将所有数据从RDD C中计算到RDD D了,再往下计算RDD F。
总结
RDD的宽窄依赖的划分是为了划分Stage,划分Stage是为了Pipline计算模型的实现,Pipline的计算模式能够以一种管道流的方式,以高阶函数的形式实现数据的本地化,传逻辑而不传输数据。在Pipline计算模式遇到持久化算子或者Shuffle(宽依赖算子)时候就会产生数据的落地。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 浅析依赖倒转、控制反转、IoC 容器、依赖注入。
- Angular 4 依赖注入教程之五 FactoryProvider配置依赖对象
- Gradle构建SpringBoot程序依赖管理之依赖版本自动控制
- Maven学习笔记七【可选的依赖项和依赖项排除】
- 模块化解耦框架RxFluxArchitecture4-依赖库与依赖注入
- 不依赖OS编译器,不依赖库,用汇编/机器码直接编程
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。