为什么这两个Spark RDD生成方式有不同的数据位置?

时间:2016-12-12 15:15:47

标签: apache-spark pyspark rdd

我在本地机器上运行两种不同的RDD生成方式,第一种方式是:

rdd = sc.range(0, 100).sortBy(lambda x: x, numPartitions=10)
rdd.collect()

第二种方式是:

rdd = sc.parallelize(xrange(100), 10)
rdd.collect()

但在我的Spark UI中,它显示了不同的数据位置,我不知道为什么。以下是第一种方式的结果,它显示了地点级别(第5列)是任意的 enter image description here

第二种方式的结果显示Locality Level是Process_Local: enter image description here

我从https://spark.apache.org/docs/latest/tuning.html读取,Process_Local Level通常比Any Level更快处理。

这是因为sortBy操作会引起shuffle然后影响数据局部吗?有人能给我一个更明确的解释吗?

1 个答案:

答案 0 :(得分:1)

你是对的。

在第一个片段中,您首先创建一个并行化集合,这意味着您的驱动程序会告诉每个工作者创建集合的某些部分。然后,至于排序每个工作节点需要访问其他节点上的数据,需要对数据进行混洗并丢失数据位置。

第二个代码段实际上甚至不是分布式作业。

由于Spark使用延迟评估,因此在调用实现结果之前不会执行任何操作,在本例中使用collect方法。第二次计算中的步骤实际上是

  1. 将类型列表的对象从驱动程序分发到工作节点
  2. 在每个工作节点上不执行任何操作
  3. 从工作人员收集分布式对象,以在驱动程序上创建类型列表对象。
  4. Spark很聪明,即使调用了parallelize,也没有理由分发列表。由于数据驻留并且计算在同一个节点上完成,因此显然保留了数据局部性。

    编辑: 关于Spark如何排序的一些额外信息。

    Spark在底层的MapReduce模型(编程模型,而不是Hadoop实现)上运行,并且sort实现为单个map和reduce。从概念上讲,在映射阶段的每个节点上,特定节点操作的集合部分被排序并写入存储器。然后,reducers从映射器中提取相关数据,合并结果并创建迭代器。

    因此,对于您的示例,假设您有一个映射器,它按顺序将数字21-34写入内存。假设同一节点有一个减速器,负责数字31-40。 reducer从驱动程序获取相关数据的信息。数字31-34从同一节点拉出,数据只需在线程之间传输。但是,其他数字可以在群集中的任意节点上,并且需要通过网络传输。一旦减速器从节点中提取了所有相关数据,则混洗阶段结束。 reducer现在合并结果(就像在mergesort中一样)并在集合的已排序部分上创建一个迭代器。

    http://blog.cloudera.com/blog/2015/01/improving-sort-performance-in-apache-spark-its-a-double/