Spark core&任务并发

时间:2016-12-05 19:06:37

标签: apache-spark architecture internal

我有一个关于火花的基本问题。我通常使用50个核心运行火花工作。在查看作业进度时,大多数时候它会显示并行运行的50个进程(正如它应该这样做),但有时它只显示并行运行的2个或4个spark进程。像这样:

[Stage 8:================================>                      (297 + 2) / 500]

正在处理的RDD在超过100个分区上repartitioned。所以这不应成为一个问题。

我有一个观察结果。我已经看到大多数时候发生的模式,SparkUI中的数据位置显示NODE_LOCAL,而有时所有50个进程都在运行,其中一些进程显示RACK_LOCAL。 这让我怀疑,这可能是因为数据在同一节点中处理之前被缓存以避免网络开销,这会减慢进一步的处理速度。

如果是这种情况,那么避免它的方法是什么。如果不是这样的话,那么会发生什么?

1 个答案:

答案 0 :(得分:3)

经过一周或更长时间的努力解决问题后,我想我已经找到导致问题的原因了。

如果您正在努力解决同样的问题,那么开始的好处是检查Spark实例是否配置正常。关于它有一个很棒的cloudera blog post

但是,如果问题不在于配置(就像我的情况那样),那么问题就出在你的代码中。问题是,有时由于不同的原因(数据源中的连接偏斜,分区不均匀等),您正在处理的RDD在2-3个分区上获取大量数据,而其余分区的数据非常少。

为了减少网络中的数据混乱,Spark尝试每个执行程序处理驻留在该节点上的本地数据。因此,2-3个执行器正在工作很长时间,其余的执行器只是在几毫秒内完成了数据。这就是我遇到上述问题所描述的问题的原因。

调试此问题的方法首先是检查RDD的分区大小。如果一个或几个分区与其他分区相比非常大,那么下一步就是在大分区中查找记录,这样您就可以知道,特别是在偏移连接的情况下,哪个密钥变得偏斜。我写了一个小函数来调试它:

from itertools import islice
def check_skewness(df):
    sampled_rdd = df.sample(False,0.01).rdd.cache() # Taking just 1% sample for fast processing
    l = sampled_rdd.mapPartitionsWithIndex(lambda x,it: [(x,sum(1 for _ in it))]).collect()
    max_part = max(l,key=lambda item:item[1])
    min_part = min(l,key=lambda item:item[1])
    if max_part[1]/min_part[1] > 5: #if difference is greater than 5 times
        print 'Partitions Skewed: Largest Partition',max_part,'Smallest Partition',min_part,'\nSample Content of the largest Partition: \n'
        print (sampled_rdd.mapPartitionsWithIndex(lambda i, it: islice(it, 0, 5)     if i == max_part[0] else []).take(5))
    else:
        print 'No Skewness: Largest Partition',max_part,'Smallest Partition',min_part

它为我提供了最小和最大的分区大小,如果这两者之间的差异超过5倍,它会打印出最大分区的5个元素,这应该可以让您大致了解分析的内容。

一旦你发现问题是倾斜的分区,你就可以找到一种方法来摆脱那个偏斜的键,或者你可以重新划分你的数据帧,这将迫使它得到平均分配,你就是&#39 ;现在看到所有的执行者将在相同的时间内工作,你会看到更少的可怕的OOM错误,处理速度也会非常快。

这些只是我作为Spark新手的两分钱,我希望Spark专家可以在这个问题上添加更多内容,因为我认为Spark世界中很多新手经常遇到类似的问题。