我正在写Spark Jobs,它在Datastax中与Cassandra交谈。
有时,在执行Spark作业中的一系列步骤时,仅获得新的RDD而不是加入旧的RDD更为容易。
您可以通过调用SparkContext [getOrCreate][1]
方法来做到这一点。
现在,在Spark Job中有时会担心,引用SparkContext会占用无法序列化的大对象(Spark Context),并尝试通过网络分发它。
在这种情况下-您正在为该JVM注册一个单例,因此它解决了序列化问题。
有一天,我的技术主管来找我说
请不要使用
SparkContext getOrCreate
,而应该使用联接
但是他没有给出原因。
我的问题是:写火花作业时是否有不使用SparkContext.getOrCreate的理由?
答案 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
实例,所以循环依赖不是问题-SparkContext
和RDDs
仅存在于其父上下文的范围内,因此您将无法提出反对属于应用程序驱动程序。
正确的资源分配是另一回事。由于每个Datasets
都会创建自己的Spark应用程序,因此您的“主”进程将无法考虑任务中初始化的上下文所使用的资源。同时,集群管理器将没有任何迹象表明应用程序或以某种方式相互连接。这可能会导致类似死锁的情况。
从技术上讲,可以仔细地分配资源并使用管理器级调度池,甚至使用具有自己的集合或资源的单独的集群管理器,也可以解决此问题,但Spark并非为之设计的,它不受支持,并且总体上会导致设计脆弱和复杂,正确性取决于配置详细信息,特定的集群管理器选择和总体集群利用率。