Spark Streaming中的checkpoint

匿名 (未验证) 提交于 2019-12-03 00:22:01

Checkpoint

我们必须记录一些信息以方便恢复现场,在Spark Streaming中使用checkpoint实现恢复操作。

Spark Streaming中有两种不同对象的checkpont操作。

元数据(Metadata) checkpointing

保存Streaming中定义流计算的相关信息到可信赖的文件系统如HDFS,这种方式用于运行Driver的节点失败之后的恢复。

元数据包括:

  • 配置---创建context时的配置
  • DStream的操作---定义流应用程序的DStream操作集
  • 未完成的批次---记录已经在队列中但是还没有完成的批次

数据(Data) checkpointing

保存生成的RDD到可信赖的存储中,有一种场景是一些有状态的transformations是跨多个批次的数据组合,生成的RDD依赖上个批次的RDD,导致RDD的依赖链随着程序运行越来越长,当程序失败后,因为依赖链过长,恢复需要相当长的时间,如果定期checkponit就可以切断依赖链以减少恢复时间。
注意:切断RDD之间的依赖链只是Data checkpointing顺带解决的问题,而不是设计Data checkpointing的目的,Data checkpointing的目的和作用还是保存RDD到可信赖的存储。

总的来说,元数据checkpoint主要是为了driver失败后的恢复,然而,如果使用上面提及的stateful transformations,RDD的checkpoint也是必要的。

checkpoint应用场景

checkpoint在以下场景中是必要的:

  1. stateful transformations:在使用updateStateByKey, reduceByKeyAndWindow这类算子之后必须使用checkpoint
  2. 从运行应用程序的驱动程序的故障中恢复――元数据检查点用于恢复进度信息。

checkpoint的使用

对于上面提及的Stateful checkpoint(第2类),可以直接使用streamingContext.checkpoint(checkpointDirectory)即可

对于方便driver恢复的checkpoint(第1类),在应用程序中必须满足以下行为:

  • 当应用程序一启动,将创建StreamingContext,配置流信息然后start()
  • 当应用程序失败之后的重新启动,将会从checkpoint目录中的checkpoint数据中恢复StreamingContext。

上面的两种行为可以用StreamingContext.getOrCreate完成。

  // Function to create and setup a new StreamingContext    def functionToCreateContext(): StreamingContext = {      val ssc = new StreamingContext(...)   // new context      val lines = ssc.socketTextStream(...) // create DStreams      ...      ssc.checkpoint(checkpointDirectory)   // set checkpoint directory      ssc    }    // Get StreamingContext from checkpoint data or create a new one    val context = StreamingContext.getOrCreate(checkpointDirectory, functionToCreateContext _)    // Do additional setup on context that needs to be done,// irrespective of whether it is being started or restarted    context. ...    // Start the context    context.start()    context.awaitTermination()  

当checkpoint目录不存在时,将重新创建context。

累加器与广播变量

累加器与广播变量不能直接从checkpoint中恢复,如果想使用累加器与广播变量,可以借助单例对象,创建一个懒加载的单例实例对象保存累加器与广播变量,当driver由于失败重新启动时,将会重新实例化这些懒加载的单例对象。

  object WordBlacklist {      @volatile private var instance: Broadcast[Seq[String]] = null      def getInstance(sc: SparkContext): Broadcast[Seq[String]] = {        if (instance == null) {          synchronized {            if (instance == null) {              val wordBlacklist = Seq("a", "b", "c")              instance = sc.broadcast(wordBlacklist)            }          }        }        instance      }}    object DroppedWordsCounter {      @volatile private var instance: LongAccumulator = null      def getInstance(sc: SparkContext): LongAccumulator = {        if (instance == null) {          synchronized {            if (instance == null) {              instance = sc.longAccumulator("WordsInBlacklistCounter")            }          }        }        instance      }}    wordCounts.foreachRDD { (rdd: RDD[(String, Int)], time: Time) =>      // Get or register the blacklist Broadcast      val blacklist = WordBlacklist.getInstance(rdd.sparkContext)      // Get or register the droppedWordsCounter Accumulator      val droppedWordsCounter = DroppedWordsCounter.getInstance(rdd.sparkContext)      // Use blacklist to drop words and use droppedWordsCounter to count them      val counts = rdd.filter { case (word, count) =>        if (blacklist.value.contains(word)) {          droppedWordsCounter.add(count)          false        } else {          true        }      }.collect().mkString("[", ", ", "]")      val output = "Counts at time " + time + " " + counts})  
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!