为什么使用单例来包装广播变量?

时间:2018-01-04 06:51:43

标签: java apache-spark spark-streaming

我在https://github.com/apache/spark/blob/master/examples/src/main/java/org/apache/spark/examples/streaming/JavaRecoverableNetworkWordCount.java

中看到了一个示例代码

代码使用singleton来包装广播变量,如下所示:

class JavaWordBlacklist {

private static volatile Broadcast<List<String>> instance = null;

public static Broadcast<List<String>> getInstance(JavaSparkContext jsc) {
  if (instance == null) {
    synchronized (JavaWordBlacklist.class) {
      if (instance == null) {
        List<String> wordBlacklist = Arrays.asList("a", "b", "c");
        instance = jsc.broadcast(wordBlacklist);
      }
    }
  }
  return instance;
}
}

并在wordCounts.foreachRDD((rdd, time) -> {...}

中填写广播变量

我的问题是,为什么不在父类中声明private static volatile Broadcast<List<String>> instance = null;,即JavaRecoverableNetworkWordCount

(在我看来,由于广播变量在foreachRDD()中初始化,在单个驱动程序线程中执行,因此这里不会出现竞争条件,因此不需要单独保护。)

1 个答案:

答案 0 :(得分:1)

这样做是为了解决检查点恢复带来的问题。请记住,检查点仅捕获元数据和/或分布式状态,而不捕获广播变量,累加器和本地对象。从检查点重新启动应用程序后,必须手动恢复所有状态。

不能解决你的观点:

  

因为广播变量是在foreachRDD()中初始化的,它在单个驱动程序线程中执行,

驱动程序不是单线程的,并且广播变量的访问目的不同于数据处理(簿记,报告)。也可以同时访问多个流。