spark学习笔记(二)

rdd 依赖

依赖关系

相邻的两个rdd之间的关系称之为依赖关系
多个连续的rdd的依赖关系称之为血缘关系(lineage)

  • 宽依赖
    同一个上游rdd 的partition 被多个下游 rdd 的 partition 依赖会引起 shuffle
阶段划分

任务的阶段划分

源码

DAGScheduler.submitJob -->

eventProcessLoop = new DAGSchedulerEventProcessLoop
eventProcessLoop.post(JobSubmitted(
      jobId, rdd, func2, partitions.toArray, callSite, waiter,
      Utils.cloneProperties(properties)))


DAGSchedulerEventProcessLoop.onReceive   dag 调度中主事件循环

==>DAGSchedulerEventProcessLoop.doOnReceive
==>{
    case JobSubmitted(jobId, rdd, func, partitions, callSite, listener, properties) =>
   dagScheduler.handleJobSubmitted(jobId, rdd, func, partitions, callSite, listener, properties)
}
==>
==>DAGScheduler.handleJobSubmitted 方法

==> finalStage = createResultStage(finalRDD, func, partitions, jobId, callSite)

val parents = getOrCreateParentStages(shuffleDeps, jobId)  ==>
{
 shuffleDeps.map { shuffleDep =>
      getOrCreateShuffleMapStage(shuffleDep, firstJobId)
    }.toList ==>{

        createShuffleMapStage(shuffleDep, firstJobId) ==>{
              val stage = new ShuffleMapStage(id, rdd, numTasks, parents, jobId, rdd.creationSite, shuffleDep, mapOutputTracker,
                            resourceProfile.id)
        }
    }
}

rdd 任务划分

rdd 的任务切分中间为 Application ,Job,Stage 和 Task

  • Application: 初始化一个 sparkContext 即 会生成一个 Application
  • Job: 一个算子就会生成一个 job
  • Stage: Satge个数等于宽依赖(shuffleDependency)的个数加1
  • Task:一个Stage 中最后一个Rdd 分区的个数就是 Task的个数
    Application -> Job -> Stage ->Task 每层都是1对n 的关系

源码:

val tasks: Seq[Task[_]] = {
      val serializedTaskMetrics = closureSerializer.serialize(stage.latestInfo.taskMetrics).array()
      stage match {
        case stage: ShuffleMapStage =>
          stage.pendingPartitions.clear()
          partitionsToCompute.map { id =>
            val locs = taskIdToLocations(id)
            val part = partitions(id)
            stage.pendingPartitions += id
            new ShuffleMapTask(stage.id, stage.latestInfo.attemptNumber,
              taskBinary, part, locs, properties, serializedTaskMetrics, Option(jobId),
              Option(sc.applicationId), sc.applicationAttemptId, stage.rdd.isBarrier())
          }

        case stage: ResultStage =>
          partitionsToCompute.map { id =>
            val p: Int = stage.partitions(id)
            val part = partitions(p)
            val locs = taskIdToLocations(id)
            new ResultTask(stage.id, stage.latestInfo.attemptNumber,
              taskBinary, part, locs, id, properties, serializedTaskMetrics,
              Option(jobId), Option(sc.applicationId), sc.applicationAttemptId,
              stage.rdd.isBarrier())
          }
      }
    } 


   ==> val partitionsToCompute: Seq[Int] = stage.findMissingPartitions()

   ==>ResultStage.findMissingPartitions(): Seq[Int] = {
    val job = activeJob.get
    (0 until job.numPartitions).filter(id => !job.finished(id))
  }

rdd 的 持久化操作

  • 由于 rdd 不保存数据 ,所以 当有重复使用同一个rdd的场景时 spark 会 根据 rdd 的依赖逻辑从头计算一遍,这样执行效率不高
    所以为了便于rdd 的 复用增加任务执行的效率 ,可以对复用的rdd 进行持久化操作

  • 对于 依赖链路 较长 的 rdd 也可以进行持久化操作

  • 会在血缘关系中添加新的依赖,一旦出现问题 可以从头读取数据

// cache 方法 默认将 数据保存在内存中
rdd.cache()

// persist 方法可以指定持久化的 保存方法 ,保存到 disk 的 文件为临时文件 在任务结束时会被删除
rdd.persist(StorageLevel.MEMORY_AND_DISK)

checkpoint 操作

checkpoint需要落盘,所以需要指定检查点保存路径,
检查点路径保存的文件,任务结束后 不会被删除

checkpoint 的调用会产生一个独立的Task 去执行检查点落盘的操作,为了提高效率 一般需要和cache() 联合使用

  • checkpoint 执行 会切断血缘关系,从新建立血缘关系,相当于读取新的数据源
//设置检查点保存路径
   sc.setCheckpointDir("/")

//设置检查点
   map.checkpoint()

自定义分区器

继承 Partitioner 类,重写方法


  def main(args: Array[String]): Unit = {
    var sparkConf = new SparkConf().setMaster("local[*]").setAppName("UserdefinePartitioner")

    var sc = new SparkContext(sparkConf)
    val value = sc.makeRDD(List(("a",3),("b", 2),("c",1) ,("a",10),("d",5),("f",20)))

    val partRdd = value.partitionBy(new MyPartitioner)
    partRdd.saveAsTextFile("output")

    sc.stop()
  }

  class  MyPartitioner extends Partitioner{
    // 分区数量
    override def numPartitions: Int = 3

    //根据数据的key值返回数据的分区索引 (从0 开始)
    override def getPartition(key: Any): Int = {
      key match {
        case "a"=>0
        case "b"=>1
        case _=>2
      }

    }
  }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值