Spark盖中盖(一篇顶五篇)-3 DAG详解

前方高能,减速慢行!

看过了Spark的核心RDD和RDD算子以后,感觉Spark是不是很神奇,竟然可以减少计算次数,优化计算。对于窄依赖是这样的,但是宽依赖怎么办?还是要等待宽依赖的结果才能继续计算。Spark引入了DAG来记录宽依赖的计算过程,这样在遇到宽依赖的时候,我们就可以一边记录当前的计算过程一边计算Stage中的窄依赖了。下面我们就来看看DAG是什么。
一、什么是DAG?
二、spark框架中DAG是做什么的?
三、DAG过程详解及源码解读
四、yarn提交任务的2种模式

一、什么是DAG?
DAG(Directed Acyclic Graph)有向无环图。
对于这个概念只有数学专业的运筹学和计算机专业的数据结构的图中讲到了DAG,所以我先普及一下理论。
图是数据结构中最复杂的,泛指无组织的结构体由关联关系形成图。DAG(有向无环图)是拓扑图的一种,比较有规律,适合做血缘关系描述。深度挖掘,机器学习,统计学都是跟图有关的,由于图不像其他数据结构一样有一个合理的组织,因此寻址的时间复杂度和空间复杂度一般都超过O(n的平方),就是要用双倍的内存或时间来查找整个图。这里给大家提供一个DAG排序的效率:500点的拓扑排序java实现要200毫秒,内存使用10M左右。或者做算法的逻辑内存转换 300毫秒 7M内存。
二、spark计算框架中DAG是做什么的?
RDD算子构建了RDD之间的关系,整个计算过程形成了一个由RDD和关系构成的DAG。
简单理解为点和线构成图。
点是某种数据结构,spark计算框架的点就是RDD(或者stage)
线就是关联关系,spark计算框架的线就是RDD算子(或者宽依赖算子)
spark计算框架中DAG分2种,getShuffleDependencies DAG 和 getMissingParentStages DAG。
getShuffleDependencies :

getShuffleDependencies

getMissingParentStages:

getMissingParentStages

仔细看上两张图,图2为图1的一部分。
这2种DAG的关系就是如此,外层的DAG遍历过程如果遇到内层 DAG直接跳入内层检索,整个过程可以看作一个大的DAG,实际作用是检索RDD数据内存位置或磁盘位置的过程。
它们的执行过程是这样的:
1,任务触发是有Action 算子触发(详见上一篇算子),查找的入口就是action算子前的最后一个RDD(finalRDD图中:RDD G),开始遍历DAG。
2,getShuffleDependencies遍历宽依赖关系,遇到窄依赖放入HashMap visit,遇到宽依赖时直接跳转到第3步。如果结束返回完成。
3,getMissingParentStages遍历窄依赖,创建resultstage(方法createResultStage),遇到窄依赖放入HashMap visit,遇到宽依赖递归第2步骤 。如果结束跳入上一步继续检索。
4,遇到可计算的stage (finalStage ),可计算指的是stage中所有RDD都可以寻址到内存或磁盘,提交stage任务到taskscheduler,taskscheduler负责分发任务到集群的worker中计算。如果结束跳入上一步继续检索。
注:2 3 步中分别维护自己的HashMap visit ,遇到宽依赖创建resultstage,这也正是上一篇中为什么宽依赖是划分stage边界的原因。

三、DAG过程详解及源码解读

DAGScheduler

getOrCreateShuffleMapStage
如上图:(只提供关键代码)
1,submitjob即任务提交到driver端,并由driver端根据RDD和算子初始化RDD的依赖关系。并调用DAGScheduler的runJob方法,runJob方法创建waiter成为DAG submitJob的开始。

  def runJob[T, U](……){
……
val waiter = submitJob(rdd, func, partitions, callSite, resultHandler, properties)
……
}```
2,submitJob方法分为3部分。
判断partition大小不在0到maxpartitions范围内抛出异常。

partitions.find(p => p >= maxPartitions || p < 0).foreach { p =>
throw new IllegalArgumentException(
"Attempting to access a non-existent partition: " + p + ". " +
"Total number of partitions: " + maxPartitions)
}```
Partition大小为0,返回空对象。

  if (partitions.size == 0) {
      return new JobWaiter[U](this, jobId, 0, resultHandler)
}```
Partition大于0则由eventProcessLoop注册DAGSchedulerEventProcessLoop并由onReceive匹配submit的提交格式。

3,作业提交到入口DAGScheduler,由DAGSchedulerEventProcessloop类判断提交任务的类型,由onReceive选择出对应的Handler(如:handleJobSubmitted,MapStageSubmitted等10几个分支)。如图上半部分DAGSchedulerEventProcessloop

private def doOnReceive(event: DAGSchedulerEvent): Unit = event match {
case JobSubmitted(jobId, rdd, func, partitions, callSite, listener, properties) =>
dagScheduler.handleJobSubmitted(jobId, rdd, func, partitions, callSite, listener, properties)
case MapStageSubmitted(jobId, dependency, callSite, listener, properties) =>
dagScheduler.handleMapStageSubmitted(jobId, dependency, callSite, listener, properties)
case ……
}```
4,当前为submitjob,所以调用JobSubmitted ,由handleJobSubmitted方法初始化job,DAG的开始是上一节讲到的最后一个RDD(finalRDD),基于这个finalRDD创建一个finalStage,并创建一个待提交的任务ActiveJob。

var finalStage: ResultStage = null 
finalStage = createResultStage(finalRDD, func, partitions, jobId, callSite)
val job = new ActiveJob(jobId, finalStage, callSite, listener, properties)

5,DAGsort 即为上一节讲到的4个过程。

  private def getMissingAncestorShuffleDependencies(
      rdd: RDD[_]): Stack[ShuffleDependency[_, _, _]] = {
    val ancestors = new Stack[ShuffleDependency[_, _, _]]
    val visited = new HashSet[RDD[_]]
      val waitingForVisit = new Stack[RDD[_]]
    waitingForVisit.push(rdd)
    while (waitingForVisit.nonEmpty) {
      val toVisit = waitingForVisit.pop()
      if (!visited(toVisit)) {
        visited += toVisit
        getShuffleDependencies(toVisit).foreach { shuffleDep =>
          if (!shuffleIdToMapStage.contains(shuffleDep.shuffleId)) {
            ancestors.push(shuffleDep)
            waitingForVisit.push(shuffleDep.rdd)
          }         }
      }
    }
    ancestors
  }```
submitstage把整个stage打包发给TaskScheduler,并有封装成taskset,分发给集群的worker计算出结果。

四、yarn提交任务的2种模式
在yarn中任务的提交分2种方式:client 模式和cluster 模式。对应的参数是:--deploy-mode client或者cluster,默认client模式。
这两种模式的区别在于driver运行在哪里。如图:
 
![yarn](http://upload-images.jianshu.io/upload_images/4115103-5fb2bfc964a780c4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
首先我们了解一下上图中的几个模块和它们的作用:
1,  Client,spark的客户端,用来提交spark任务。
2,  Driver,用来接收client提交的任务,构建lineage(RDD血缘关系),DAG检索,序列化,注册应用,提交task执行任务,与worker节点通信(master提交完任务worker会反注册到driver端)。
3,  Master,计算框架主节点(yarn的applicationMaster)。负责任务分配和管理。
4,  Worker,计算框架工作节点,spark计算框架中的worker内部关系是:worker= executer =多个task
在Yarn中(参数是--master yarn)执行任务的2种模式:
Client模式:driver在applicationMaster端。
Cluster模式:dirver是在worker端。
到这里关于本期DAG的讲解就结束了,不知各位是否有头晕眼花手指酸的感觉,希望本文对您能有些许帮助。因本人理论水平和写作能力有限,有些表达歧义或错漏还请谅解,此理论仅为引导,您的实践才是检验真理的唯一标准。后续我们会继续聊一聊spark的其他事儿,还请关注,后会有期!
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容