是否可以从Spark-streaming检查点恢复广播值

时间:2016-03-02 02:46:53

标签: spark-streaming

我使用hbase-spark在我的spark-streaming项目中记录pv / uv。然后,当我杀死应用程序并重新启动它时,我在检查点恢复时遇到异常:

  

16/03/02 10:17:21错误HBaseContext:无法从广播中获取getConfig   java.lang.ClassCastException:[B无法强制转换为org.apache.spark.SerializableWritable       在com.paitao.xmlife.contrib.hbase.HBaseContext.getConf(HBaseContext.scala:645)       at com.paitao.xmlife.contrib.hbase.HBaseContext.com $ paitao $ xmlife $ contrib $ hbase $ HBaseContext $$ hbaseForeachPartition(HBaseContext.scala:627)       at com.paitao.xmlife.contrib.hbase.HBaseContext $$ anonfun $ com $ paitao $ xmlife $ contrib $ hbase $ HBaseContext $$ bulkMutation $ 1.apply(HBaseContext.scala:457)       at com.paitao.xmlife.contrib.hbase.HBaseContext $$ anonfun $ com $ paitao $ xmlife $ contrib $ hbase $ HBaseContext $$ bulkMutation $ 1.apply(HBaseContext.scala:457)       在org.apache.spark.rdd.RDD $$ anonfun $ foreachPartition $ 1 $$ anonfun $ apply $ 29.apply(RDD.scala:898)       在org.apache.spark.rdd.RDD $$ anonfun $ foreachPartition $ 1 $$ anonfun $ apply $ 29.apply(RDD.scala:898)       在org.apache.spark.SparkContext $$ anonfun $ runJob $ 5.apply(SparkContext.scala:1839)       在org.apache.spark.SparkContext $$ anonfun $ runJob $ 5.apply(SparkContext.scala:1839)       在org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:66)       在org.apache.spark.scheduler.Task.run(Task.scala:88)       在org.apache.spark.executor.Executor $ TaskRunner.run(Executor.scala:214)       在java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)       at java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:617)       在java.lang.Thread.run(Thread.java:745)

我检查了HBaseContext的代码,它使用广播来存储HBase配置。

class HBaseContext(@transient sc: SparkContext,
               @transient config: Configuration,
               val tmpHdfsConfgFile: String = null) extends Serializable with Logging {

    @transient var credentials = SparkHadoopUtil.get.getCurrentUserCredentials()
    @transient var tmpHdfsConfiguration: Configuration = config
    @transient var appliedCredentials = false
    @transient val job = Job.getInstance(config)

    TableMapReduceUtil.initCredentials(job)
    // <-- broadcast for HBaseConfiguration here !!!
    var broadcastedConf = sc.broadcast(new SerializableWritable(config))
    var credentialsConf = sc.broadcast(new SerializableWritable(job.getCredentials()))
    ...

当checkpoint-recover时,它试图在其getConf函数中访问此广播值:

if (tmpHdfsConfiguration == null) {
  try {
    tmpHdfsConfiguration = configBroadcast.value.value
  } catch {
    case ex: Exception => logError("Unable to getConfig from broadcast", ex)
  }
}

然后引发异常。我的问题是:是否有可能在spark应用程序中从检查点恢复广播值?我们还有一些其他解决方案可以在恢复后重新广播值吗?

感谢您的反馈!

2 个答案:

答案 0 :(得分:1)

目前,它是Spark的一个已知错误。贡献者一直在调查这个问题,但没有取得任何进展。

这是我的解决方法:我不是将数据加载到广播变量并向所有执行者广播,而是让每个执行者将数据本身加载到单个对象中。

顺便说一句,请按照此问题进行更改https://issues.apache.org/jira/browse/SPARK-5206

答案 1 :(得分:1)

遵循以下方法

  1. 创建火花上下文。
  2. 初始化广播变量。
  3. 使用上述spark上下文并通过检查点目录创建流上下文,并传递已初始化的广播变量。

当流作业在检查点目录中没有数据开始时,它将初始化广播变量。

重新启动流式传输时,它将从检查点目录中恢复广播变量。