scala - 编写火花作业时是否有理由不使用 SparkContext.getOrCreate?
问题描述
我正在编写与 Datastax 中的 Cassandra 对话的 Spark Jobs。
有时,在 Spark 作业中执行一系列步骤时,获得一个新的 RDD 比加入旧的 RDD 更容易。
您可以通过调用该SparkContext [getOrCreate][1]
方法来做到这一点。
现在有时在 Spark 作业中会担心引用 SparkContext 可能会获取一个不可序列化的大对象(Spark 上下文)并尝试通过网络分发它。
在这种情况下 - 您正在为该 JVM 注册一个单例,因此它解决了序列化问题。
有一天,我的技术主管来找我说
不要使用
SparkContext getOrCreate
你可以并且应该使用连接来代替
但他没有给出理由。
我的问题是:编写 Spark 作业时是否有理由不使用 SparkContext.getOrCreate?
解决方案
TL;DR这些方法有许多合法的应用,getOrCreate
但试图找到漏洞来执行映射端连接并不是其中之一。
一般来说,没有什么严重的错误SparkContext.getOrCreate
。该方法有其应用,尽管有一些警告,最值得注意的是:
- 在其最简单的形式中,它不允许您设置特定于作业的属性,并且第二个变体 (
(SparkConf) => SparkContext
) 需要传递,这对于将/保持在范围内SparkConf
几乎没有改进。SparkContext
SparkSession
- 它可能导致具有“魔术”依赖性的不透明代码。它会影响测试策略和整体代码的可读性。
但是你的问题,特别是:
现在有时在 Spark 作业中会担心引用 SparkContext 可能会获取一个不可序列化的大对象(Spark 上下文)并尝试通过网络分发它
和
不要使用
SparkContext
getOrCreate
你可以并且应该使用连接来代替
建议您实际上以从未打算使用的方式使用该方法。通过SparkContext
在执行程序节点上使用。
val rdd: RDD[_] = ???
rdd.map(_ => {
val sc = SparkContext.getOrCreate()
...
})
这绝对是你不应该做的事情。
每个 Spark 应用程序都应该有一个,并且只有一个SparkContext
在驱动程序上初始化,并且 Apache Spark 开发人员做了很多工作,以防止用户尝试SparkContex
在驱动程序之外使用。这不是因为SparkContext
它很大,或者不可能序列化,而是因为它是 Spark 计算模型的基本特征。
你可能知道,Spark 中的计算是由一个有向无环依赖图来描述的,它:
- 以可以转化为实际任务的方式描述处理管道。
- 在任务失败的情况下启用正常恢复。
- 允许适当的资源分配并确保没有循环依赖。
让我们专注于最后一部分。由于每个执行程序 JVM 都有自己的SparkContext
循环依赖实例,这不是问题 -RDDs
并且Datasets
仅存在于其父上下文的范围内,因此您将无法访问属于应用程序驱动程序的对象。
适当的资源分配是另一回事。由于每个人都SparkContext
创建了自己的 Spark 应用程序,因此您的“主”进程将无法考虑任务中初始化的上下文所使用的资源。同时集群管理器不会有任何迹象表明应用程序或以某种方式互连。这可能会导致类似死锁的情况。
技术上可以绕过它,仔细分配资源并使用管理器级别的调度池,甚至是具有自己的集合或资源的单独集群管理器,但这不是 Spark 设计的,它不支持,并且总体上会导致脆弱和复杂的设计,其中正确性取决于配置细节、特定的集群管理器选择和整体集群利用率。
推荐阅读
- haskell - 使用 Cabal 升级包依赖项
- javascript - VS Code Extensions API 未记录的函数“exports.deactivate”
- asp.net-core-2.0 - 从 Azure AC B2C 获取令牌
- autodesk-forge - 在查看器中放大房间
- javascript - 如何在 React 的现有 Leaflet 地图中编辑/修改图层源?
- python - Selenium Chromedriver 错误加载配置文件
- angular - 更改页面或 javascript 停止工作时,Angular5 应用程序需要硬刷新
- python - 女服务员 Nginx 无法提供具有相对路径的静态文件
- c# - 返回字符串而不是整数
- python - Django orm - 如何在不同日期的查询中获取不同的字段项