有没有理由在编写火花作业时不使用SparkContext.getOrCreate?

时间:2018-07-03 11:36:59

标签: scala apache-spark cassandra datastax

我正在写Spark Jobs,它在Datastax中与Cassandra交谈。

有时,在执行Spark作业中的一系列步骤时,仅获得新的RDD而不是加入旧的RDD更为容易。

您可以通过调用SparkContext [getOrCreate][1]方法来做到这一点。

现在,在Spark Job中有时会担心,引用SparkContext会占用无法序列化的大对象(Spark Context),并尝试通过网络分发它。

在这种情况下-您正在为该JVM注册一个单例,因此它解决了序列化问题。

有一天,我的技术主管来找我说

  

请不要使用SparkContext getOrCreate,而应该使用联接

但是他没有给出原因。

我的问题是:写火花作业时是否有不使用SparkContext.getOrCreate的理由?

1 个答案:

答案 0 :(得分:3)

TL; DR getOrCreate方法有很多合法的应用程序,但是尝试寻找漏洞来执行地图端连接并不是其中之一。

通常,SparkContext.getOrCreate并没有什么大不了的。该方法有其应用,尽管有一些警告,但最值得注意的是:

  • 以最简单的形式,它不允许您设置作业特定的属性,第二个变体((SparkConf) => SparkContext)要求传递SparkConf,这与保持{{1} } / SparkContext
  • 它可能导致具有“魔术”依赖性的不透明代码。它会影响测试策略和整体代码可读性。

但是您的问题特别是:

  

现在在Spark Job中有时会担心,引用SparkContext可能会占用无法序列化的大对象(Spark Context),并尝试通过网络分发它

  

请勿使用SparkSession SparkContext,而应该使用联接

建议您实际上以从未使用过的方式使用该方法。通过在执行程序节点上使用getOrCreate

SparkContext

这绝对是你不应该做的事情。

每个Spark应用程序应该在驱动程序上初始化一个,并且只有一个val rdd: RDD[_] = ??? rdd.map(_ => { val sc = SparkContext.getOrCreate() ... }) 初始化,并且大量的Apache Spark开发人员阻止用户尝试在驱动程序之外使用SparkContext。并不是因为SparkContex大或无法序列化,而是因为它是Spark计算模型的基本特征。

您可能知道,Spark中的计算是通过有向非依赖性有向图来描述的,

  • 以可以转化为实际任务的方式描述处理管道。
  • 在任务失败的情况下启用正常恢复。
  • 允许适当的资源分配,并确保没有循环依赖性。

让我们专注于最后一部分。由于每个执行者JVM都有自己的SparkContext实例,所以循环依赖不是问题-SparkContextRDDs仅存在于其父上下文的范围内,因此您将无法提出反对属于应用程序驱动程序。

正确的资源分配是另一回事。由于每个Datasets都会创建自己的Spark应用程序,因此您的“主”进程将无法考虑任务中初始化的上下文所使用的资源。同时,集群管理器将没有任何迹象表明应用程序或以某种方式相互连接。这可能会导致类似死锁的情况。

从技术上讲,可以仔细地分配资源并使用管理器级调度池,甚至使用具有自己的集合或资源的单独的集群管理器,也可以解决此问题,但Spark并非为之设计的,它不受支持,并且总体上会导致设计脆弱和复杂,正确性取决于配置详细信息,特定的集群管理器选择和总体集群利用率。