Githup项目LearningSpark代码讲解(二)

import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkContext, SparkConf}

object Ex2_Computations {

  /**
    * 这个方法就是将信息按照树形模型打印,前面每一级加了一个' '
    * @param r
    * @param depth
    * @tparam T
    */
  private def showDep[T](r: RDD[T], depth: Int) : Unit = {
    println("".padTo(depth, ' ') + "RDD id=" + r.id)
    r.dependencies.foreach(dep => {
      showDep(dep.rdd, depth + 1)
    })
  }
  def showDep[T](r: RDD[T]) : Unit = {
    showDep(r, 0)
  }

  def main(args: Array[String]) {
    val conf = new SparkConf().setAppName("Ex2_Computations").setMaster("local[4]")
    val sc = new SparkContext(conf)

    /**
      * 以下这部分和上一篇相同,就是把值乘100再加一
      * toDebugString是按照debug模式打印RDD信息方便在不能断点的地方调试
      *
      */
    val numbers = sc.parallelize(1 to 10, 4)
    val bigger = numbers.map(n => n * 100)
    val biggerStill = bigger.map(n => n + 1)

    println("以Debug string模式打印RDD 'biggerStill'")
    println(biggerStill.toDebugString)

    /**
      * reduce操作比较简单,就是将整个集合的操作做类似如下操作
      * int i = 0
      * for(j=1;j<n;j++){
      *   i = i+j
      * }
      *就是将所有Seq中的元素按顺序执行一遍
      */
    val s = biggerStill.reduce(_ + _)

    println("sum = " + s)

    /**
      * 以下部分都是对相关信息的打印
      * 这里面注意这几个id值,这几个id值是这个代码主要想讲述的东西
      * IDs of the various RDDs
      * numbers: id=0
      * bigger: id=1
      * biggerStill: id=2
      * dependencies working back from RDD 'biggerStill'
      * RDD id=2
      *   RDD id=1
      *     RDD id=0
      * 这里面的意思是biggerStill依赖于bigger,而bigger依赖于numbers
      */
    println("IDs of the various RDDs")
    println("numbers: id=" + numbers.id)
    println("bigger: id=" + bigger.id)
    println("biggerStill: id=" + biggerStill.id)
    println("dependencies working back from RDD 'biggerStill'")
    showDep(biggerStill)

    /**
      * bigger ++ biggerStill
      * 相当于两个RDD进行拼接其他与上面相同
      * moreNumbers: id=3
      * RDD id=3
      *   RDD id=1
      *     RDD id=0
      * RDD id=2
      *   RDD id=1
      *     RDD id=0
      */
    val moreNumbers = bigger ++ biggerStill
    println("The RDD 'moreNumbers' has mroe complex dependencies")
    println(moreNumbers.toDebugString)
    println("moreNumbers: id=" + moreNumbers.id)
    showDep(moreNumbers)

    /**
      * 这个cache()比较重要,他的意思是缓存中的内容可能会丢失,因此依赖关系树不会被丢弃。
      * cache 和 checkpoint 之间有一个重大的区别,cache 将 RDD 以及 RDD 的血统(记录了这个RDD如何产生)缓存到内存中,
      * 当缓存的 RDD 失效的时候(如内存损坏),它们可以通过血统重新计算来进行恢复。
      * 但是 checkpoint 将 RDD 缓存到了 HDFS 中,同时忽略了它的血统(也就是RDD之前的那些依赖)。
      * 为什么要丢掉依赖?因为可以利用 HDFS 多副本特性保证容错!
      */
    moreNumbers.cache()
    println("cached it: the dependencies don't change")
    println(moreNumbers.toDebugString)
    showDep(moreNumbers)


    /**
      * 下面这一部分演示了checkpoint的作用
      * 有时候,Transformation 的 RDD 非常多或者具体 Transformation 产生的 RDD 本身计算特别复杂和耗时,此时我们必须考虑对计算结果数据进行持久化。与 persist 不同,persist 是优先将结果放入内存,内存不够的情况下,会放在磁盘。无论是放内存还是磁盘,都是不可靠的。Checkpoint 的产生就是为了相对而言更加可靠的持久化数据。
      * 1. Checkpoint 可以指定把数据放在本地并且是多副本的方式,但是正常的生产环境下是放在 HDFS 上的,这就保证了中间计算结果持久化的高可靠性。
      * 2. 在进行 RDD 的 Checkpoint 的时候其所依赖的所有的 RDD 都会从计算链条中清空掉
      * 3. 作为最佳实践,一般在进行 checkpoint 方法调用前通常都要进行 persist 来把当前 RDD 的数据持久化到内存或者磁盘上,这是因为 checkpoint 是 Lazy 级别的,必须有 Job 的执行且在 Job执行后才会从后往前回溯哪个 RDD 进行了 checkpoint 标记,然后对标记了要进行 checkpoint 的 RDD 新启动一个 Job 执行具体的 Checkpoint 的过程。
      * 4. Checkpoint 改变了 RDD 的 Lineage。
      * 5. checkpoint 是另外启动一个 Job,并重新计算。而不是复用计算完的结果。因此建议在 checkpoint 之前进行 cache 操作。
      */
    println("has RDD 'moreNumbers' been checkpointed? : " + moreNumbers.isCheckpointed)
    // set moreNumbers up to be checkpointed
    sc.setCheckpointDir("/tmp/sparkcps")
    moreNumbers.checkpoint()
    // it will only happen after we force the values to be computed
    println("NOW has it been checkpointed? : " + moreNumbers.isCheckpointed)
    moreNumbers.count()
    println("NOW has it been checkpointed? : " + moreNumbers.isCheckpointed)
    println(moreNumbers.toDebugString)
    showDep(moreNumbers)

    // again, calculations are not done until strictly necessary
    println("this shouldn't throw an exception")
    val thisWillBlowUp = numbers map {
      case (7) => { throw new Exception }
      case (n) => n
    }

    // notice it didn't blow up yet even though there's a 7
    println("the exception should get thrown now")
    try {
      println(thisWillBlowUp.count())
    } catch {
      case (e: Exception) => println("Yep, it blew up now")
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值