Spark笔记四之RDD处理过程

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/ty4315/article/details/71104651

Spark任务调度

Spark的任务调度分为四步

1RDD objects

  RDD的准备阶段,组织RDD及RDD的依赖关系生成大概的RDD的DAG图,DAG图是有向环图。

 

2DAG scheduler

         细分RDD中partition的依赖关系确定那些是宽依赖那些是窄依赖,生成更详细的DAG图,将DAG图封装成 TaskSet任务集合当触发计算时(执行action型算子)将其提交给集群。

 

3TaskScheduler

         接收TaskSet任务集,分析确定那个task对应那个worker并将其发送给worker执行。

 

4worker执行阶段

         接收task任务,通过spark的block管理器blockManager从集群节点上获取对应的block上的数据,启动executor完成计算。

 

Task执行过程

1.执行action型算子时将task发给对应的worker然后worker启动executor执行计算。

2.executor获取运行环境调用task类的run方法执行计算。

Task类是一个抽象类,类中的run方法调用了一个runTask的抽象方法。


3.执行任务时task任务分为两种,shuffleMapTask和resultTask。

shuffleMapTask:是DAG任务所有执行的中间过程都生成shuffleMapTask

resultTask:是为最终结果的partition生成。

shuffleMapTask继承了task抽象类并实现了runTask方法。在runTask方法中对rdd进行迭代计算,此迭代方法在RDD类中。


进入iterator方法可以看到,首先看到两个判断。

A缓存级别是否为NONE如果不是则执行如下操作

         SparkEnv.get.cacheManager.getOrCompute(this,split, context, storageLevel)

         SparkEnv:是spark当前的环境变量它存储了spark的环境信息如主机端口等。此类中有一个常量cacheManager,调用这个缓存类的getOrCompute方法获取RDD,如果之前有缓存则直接取如果没有则进行计算


在CacheManager中的getOrCompute方法通过RDD的id和partition的序号获取blockId再通过blockManager获取对应block上的数据。从下图的代码中看到若已缓存则直接返回值没有则需要计算,计算时会加锁。


B如果缓存为NONE则判断checkpoint检查点,如果有检查点则从检查点中读取否则重新计算RDD

 

缓存策略

在if (storageLevel != StorageLevel.NONE) 中对象StorageLevel定义了spark的缓存策略


NONE:不缓存

DISK_ONLY:只向磁盘缓存

DISK_ONLY_2:向磁盘缓存两份

MEMORY_ONLY:只向内存缓存,默认使用此种策略

MEMORY_ONLY_SER:只向内存缓存序列化RDD,占用空间小但需要反序列化

OFF_HEAP:缓存到堆外不受jvm管理

后面有2的代表是两份数据

 

缓存RDD调用RDD类的cache方法和persist方法


checkpoint检查点

检查点是将RDD保存到磁盘上,但是不保存RDD之间的依赖关系会切断RDD与之前RDD的关系,这是它与persist的重要区别

以下是checkpoint代码示例

package spark_project1

import org.apache.spark.SparkConf
import org.apache.spark.SparkContext
import org.apache.spark.SparkContext._

object checkPoint {
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf
    conf.setAppName("test")
    conf.setMaster("local[*]")
    
    val sc = new SparkContext(conf)
    sc.setCheckpointDir("hdfs://shb01:9000/checkPoint01")
    
    val rs = sc.textFile("d:/test/*").flatMap(_.split("\t")).map((_,1)).reduceByKey((x:Int,y:Int) => (x + y))
    rs.checkpoint()
    rs.collect()
    
  }
}



展开阅读全文

没有更多推荐了,返回首页