在Spark-land中有几个相似但又不同的概念,围绕如何将工作分配给不同的节点并并发执行。具体来说,有:
- Spark Driver节点(
sparkDriverCount
) - Spark集群(
numWorkerNodes
)可用的工作节点数 - Spark执行器数量(
numExecutors
) - 所有工作/执行程序同时操作的数据帧(
dataFrame
) -
dataFrame
(numDFRows
)的行数 -
dataFrame
(numPartitions
)上的分区数 - 最后,每个工作节点上可用的CPU核数(
numCpuCoresPerWorker
)
我相信所有的Spark集群都有一个且只有一个 Spark Driver,然后是0+ worker节点。如果我错了,请先纠正我!假设我说的差不多正确,我们在这里锁定几个变量。假设我们有一个Spark集群,其中有1个Driver节点和4个Worker节点,每个Worker节点上有4个CPU内核(因此总共有16个CPU内核)。所以这里的"given"是:
sparkDriverCount = 1
numWorkerNodes = 4
numCpuCores = numWorkerNodes * numCpuCoresPerWorker = 4 * 4 = 16
考虑到这个设置,我想知道如何确定一些事情。具体来说:
-
numWorkerNodes
和numExecutors
是什么关系?工作人员与执行者之间是否存在某种已知/普遍接受的比例?是否有办法确定numExecutors
给定numWorkerNodes
(或任何其他输入)? -
numDFRows
/numPartitions
是否有一个已知的/普遍接受的/最佳的比值?如何根据dataFrame
的大小计算"最佳"分区数? - 我从其他工程师那里听说,一般的"经验法则"是:
numPartitions = numWorkerNodes * numCpuCoresPerWorker
,这是真的吗?换句话说,它规定每个CPU内核应该有一个分区。
是的,一个spark应用程序只有一个Driver。
numWorkerNodes
和numExecutors
是什么关系?
一个worker可以承载多个executor,你可以把它想象成worker是集群的机器/节点,executor是运行在该worker上的进程(在核心中执行)。
所以' numWorkerNodes <= numExecutors'.
他们有口粮吗?
就我个人而言,我在一个假集群中工作,我的笔记本电脑是驱动程序,同一台笔记本电脑中的虚拟机是工作人员,和在一个>10k节点的工业集群中,我不需要关心这些,因为似乎spark会照顾到这一点。
我只使用:
--num-executors 64
当我启动/提交我的脚本和spark知道,我猜,它需要召唤多少工人(当然,通过考虑其他参数,以及机器的性质)。
因此,就我个人而言,我不知道任何这样的比例。
numDFRows
/numPartitions
是否有一个已知的/普遍接受的/最佳的比值?
我不知道有一个,但根据经验,您可以依赖#executor与#executor的乘积。核数,然后乘以3或4。当然这是一个启发式。在pyspark中,它看起来像这样:
sc = SparkContext(appName = "smeeb-App")
total_cores = int(sc._conf.get('spark.executor.instances')) * int(sc._conf.get('spark.executor.cores'))
dataset = sc.textFile(input_path, total_cores * 3)
如何根据
DataFrame
的大小计算"最佳"分区数?
这是个好问题。当然,这很难回答,这取决于你的数据、集群等,但正如我在这里与自己讨论的那样。
太少的分区,你将有巨大的数据块,特别是当你处理大数据时,从而给你的应用程序带来内存压力。
分区太多,你会让hdfs承受更大的压力,因为所有必须从hdfs生成的元数据都随着分区数量的增加而显著增加(因为它维护临时文件等)。<一口> * 一口>
因此,您需要的是为分区数量找到一个最佳点,这是微调应用程序的一部分。:)"经验法则"是:
numPartitions = numWorkerNodes * numCpuCoresPerWorker
,是真的吗?
啊,在看到这个之前,我正在写上面的启发式。所以这个问题已经有了答案,但是考虑到worker和executor的区别。
*我今天失败了:通过Python用Spark准备我的大数据,当使用太多分区导致Active tasks在Spark UI中是一个负数