我是Spark的新手。如何知道哪一段代码将在驱动程序上运行?哪个会在执行者身上运行?
我们是否总是必须尝试编码以使所有内容都在执行程序上运行?是否有任何建议/方法可以使您的大部分代码在执行程序上运行?
更新:据我所知,转换运行在执行程序&动作在驱动程序上运行,因为它需要返回值。如果动作在驱动程序上运行还是应该在执行程序上运行,那么这样可以吗?驱动程序实际运行在哪里?在群集上?
答案 0 :(得分:22)
任何Spark应用程序都包含一个Driver进程和一个或多个Executor进程。 Driver进程将在集群的Master节点上运行,Executor进程在Worker节点上运行。您可以根据使用情况动态增加或减少Executor进程的数量,但驱动程序进程将在应用程序的整个生命周期中存在。
驱动程序进程负责很多事情,包括指导应用程序的整体控制流程,重新启动失败的阶段以及应用程序处理数据的整个高级方向。
编写应用程序以便Executors处理更多数据更多地属于优化应用程序的范围,以便更有效/更快地处理数据,从而利用群集中可用的所有资源。 实际上,您并不需要担心确保执行程序正在处理更多数据。
话虽如此,有一些动作,一旦触发,必然涉及到数据的混乱。如果您在RDD上调用collect
操作,则所有数据都会被带到驱动程序进程,如果您的RDD中包含足够大量的数据,则应用程序将触发Out Of Memory
错误,因为运行Driver进程的单个机器将无法保存所有数据。
牢记上述内容,转换是懒惰的,而动作则不是。 转换基本上将一个RDD转换为另一个RDD。但是在RDD上调用转换实际上并不会导致任何数据在任何地方被处理,Driver或Executor。所有的转换都是它添加到DAG的谱系图中,该谱图将在调用Action时执行。
因此,当您在RDD上调用Action时,会发生实际处理。最简单的例子是调用collect
。一旦调用了一个动作,Spark就会工作并在指定的RDD上执行先前保存的DAG计算,并返回结果。执行这些计算的地方完全取决于您的应用程序。
答案 1 :(得分:18)
这里没有简单明了的答案。
根据经验,在mapPartitions
(map
,filter
,flatMap
)或combineByKey
等高阶函数的闭包内执行的所有内容都应该主要由执行机器处理。在这些之外的所有操作都由驾驶员处理。但你必须意识到这是一个严重的简化。
根据具体的方法和语言,驱动程序至少可以处理部分作业。例如,当您使用combine
- 类似方法(reduce
,aggregate
)时,最终合并将在驱动程序计算机上本地应用。复杂算法(如许多ML / MLlib工具)可以在需要时交错分布式和本地处理。
此外,数据处理只是整个工作的一小部分。驱动程序负责bookeeping,累加器处理,初始广播和其他辅助任务。它还处理谱系和DAG处理,并为更高级别的API(Dataset
,SparkSQL
)生成执行计划。
虽然整体情况在实践中相对复杂,但您的选择相对有限。你可以:
collect
,toLocalIterator
)以进行本地处理。tree*
(treeAggregate
,treeReduce
)方法对工作人员执行更多工作。