反应各RDD之间关系,即把第一个RDD和最后一个RDD 串联起来的关系图。
根据DAG 能够找到每个RDD的父RDD
executor是 驻守在各个工作节点中的一个进程,负责生成线程 来执行分配给该工作节点的任务
程序员编写的一整个代码文件,比如一个 wordcount 代码文件
executor派生出的一个个 线程,每一个线程处理一个任务
Job=多个stage,Stage=多个同种task
一个application 会被且分为多个 作业,每个作业 又会被且分为 多个任务子集 也叫阶段stage, 每个阶段又被分为 很多个 任务, 每个任务被分配到多个工作节点上 执行
一个作业包含了 多个RDD 以及对RDD的操作
Job=多个stage,Stage=多个同种task
7.sparkContext
存在于 Driver 节点中,相当于在指挥所中的 指挥官
sparkcontxt 在收到application后 , 负责向资源管理器申请资源
然后切分作业,
主要分为3部分:Driver 节点、 资源管理器节点、工作节点
执行顺序:
首先用户提交的代码 会提交到Driver端中,Driver端(相当于一个指挥所)会生成一个sparkContext(相当于一个指挥官)
那么 sparkContext 会根据提交的代码,(这些代码其实就是对RDD的操作), 生成DAG有向无环图, 记录了上游到下游 各RDD之间依赖关系和对每个RDD的操作。
所以DAG中包含了两部分内容,第一部分,整个RDD的依赖关系,即从第一个到最后一个RDD串联起来的关系图,根据这个可以找到每个RDD的父RDD。
第二部分,记录了对每个RDD 的操作,比如是 转换操作Transformation 或 动作操作Action.
DAG schedule 会干两件事情,切分job 和 切分stage
DAG schedule 会把DAG 切分成不同的job(也就是分为不同的作业)(每遇到一个Action算子操作,就切分一个作业Job )
每个Job中包含很多stage, 相当于一个个子作业(每遇到一个宽依赖就切分stage,根据shuffle切分),stage中包含了很多的任务,是一个任务集合,所以stage 也是一个 task set 集合
Job=多个stage,Stage=多个同种task
task schedule 会负责具体把任务,分配到 哪个工作节点上去
在这个过程中 task schedule 并不是直接把 任务 扔给工作节点,而是各个工作节点向task schedule 申请/请求任务。
那么task schedule会 根据“计算向数据靠拢”原则, 把任务分给对应的工作节点。 即 数据储存在哪个工作节点work node上,就把这部分数据相关的计算 任务,分给该work node,完成本地化处理。
task scedule 找到最优工作节点后,会把任务分配过去,其实就是 我们编写的那些 对RDD操作的 代码传过去。
然后 task schedule 再返回给 DAG schedule ,然后 DAG schedule 再返回给 SparkContext,由sparkContext 最后把结果返回给用户,或写入HDFS或其他存储中去。
ps:在整个过程中,sparkContext 是用户操作和 集群,建立连接的 一个通道
DAG schedule 划分的主要依据是 各个RDD之间的依赖关系, 有两种依赖关系:宽依赖和窄依赖
如果是宽依赖 那就切分stage
如果是窄依赖 不切分
RDD之间是 宽依赖 或 窄依赖 主要看 两个RDD之间 有没有shuffle 即洗牌操作
如果从父RDD 到子RDD的时候 ,发生了 shuffle ,那么这两个 RDD就是 宽依赖, 那就会被DAG schedule 切分为两个 stage 阶段/作业
如果 父RDD 到子RDD的时候,没发生shuffle ,那么是窄依赖, 不会切分 stage
shuffle 中文意思是 洗牌,
那么对数据进行 打散重新分配,这个过程其实就是shuffle
如下图,文件中的数据, 传给了 3台 map节点,那么这3台蓝色的 map节点 处理完数据后, 要把数据传给 黄色的3台 reduce 节点,
关键点 就在这 3台蓝色的map节点是怎么 传给 黄色 3台reduce 节点的,
其实是 把map节点 所有数据进行 盘点洗牌,找到 (a, 1) 元素发给 reduce1节点,找到 (b, 1) 元素发给 reduce2节点.....
这个就是洗牌,对数据进行重新清洗,找到 特定元素 发给特定 节点。
shuffle 是需要大量的 节点之间的 网络IO开销的,并且shuffle一定会落磁盘。
有2种情况:
一个父RDD 对应多个 子RDD
因为如果 一个父RDD 对应多个 子RDD ,那么父RDD 会进行洗牌操作,找到特定的元素 发给特定的 某个子节点。
DAG schedule 根据RDD之间的宽窄依赖关系,划分stage ,其实是为了提高数据处理的效率,为了实现流水线优化。
简单点说 spark只能对 窄依赖进行优化, 宽依赖没法优化,所以要把宽窄依赖分开。
首先,在并行处理有2个基本的操作,fork 和 join , fork 是分发 ,join是汇集
spark的流水线优化 其实就是对 不必要的join的 优化,减少不必要join,因为 join就可能有时间的等待
比如说,要实现把 北京一个学校的学生 送到厦门,根据宽窄依赖不同 可以有2种方案
如下图, 分别由班长带男生 和 组织委员带女生 ,分别乘坐飞机(并行处理),先飞往上海 集合后,再由班长带领男生 、组织委员带女生 ,从上海飞往厦门。
那么在这个过程中 由于要在上海集合, 所以班长带的男生 到达上海后 ,需要等待1小时的 女生,
然后,两班人马 从上海出发 到厦门后,又要 集合,所以 女生要等 男生1小时,
所以,全程用了 6小时。
在上边的例子中,班长带男生到上海后,等女生 1小时,其实是可以优化掉的, 班长可以直接从北京到厦门,组织委员也是
这个就是 DAG的流水线优化最基本原理
班长在带领 男生到上海后,需要带领 1班的学生去厦门, 而组织委员在带领女生到上海后,需要带领 2班学生去厦门
那么在 上海这个环节 就需要把同学重新分配,组织委员带领的1班女生要到 班长那边去 ,班长带的2班男生要到 组织委员那边去,
就有重新洗牌的操作了,就有shuffle,
而且班长提前到达 上海后,必须等组织委员和女生都到达以后 才能出发, 这也就是 宽依赖不能优化的原因。
宽依赖一定会落磁盘
如下图,A -> B 就是一个宽依赖, 所以A这部分 ,就切分为 一个stage
然后 C -> D -> F都是窄依赖 , F -> G 是宽依赖 ,所以 C D F是一个stage
最后 G汇总又是一个stage
一共3个stage