什么时候在Apache Spark中发生改组?

时间:2015-07-13 14:49:12

标签: mapreduce apache-spark

我正在优化Spark中的参数,并且想知道Spark是如何改变数据的。

准确地说,我有一个简单的字数统计程序,想知道spark.shuffle.file.buffer.kb如何影响运行时间。现在,当我将此参数设置得非常高时,我只看到减速(我猜这会阻止每个任务的缓冲区同时适应内存)。

有人可以解释Spark是如何进行缩减的吗?例如,数据在RDD中读取和分区,并且当调用“action”函数时,Spark会将任务发送到工作节点。如果操作是减少,Spark如何处理此问题,以及与此过程相关的shuffle文件/缓冲区如何?

2 个答案:

答案 0 :(得分:14)

问题:关于在Spark上触发洗牌时的问题?

答案:任何joincogroupByKey操作都涉及将对象保存在哈希映射或内存缓冲区中以进行分组或排序。 joincogroupgroupByKey在这些数据结构中使用这些数据结构,这些数据结构位于它们触发的随机播放的提取端。 reduceByKeyaggregateByKey在他们触发的随机播放两侧的阶段的任务中使用数据结构。

说明:如何在Spark中进行随机播放操作?

与Hadoop相比,Spark中的shuffle操作实现方式不同。我不知道你是否熟悉它如何与Hadoop一起使用,但现在让我们专注于Spark。

映射端,Spark中的每个map任务都会为每个reducer写一个shuffle文件(os磁盘缓冲区) - 它对应于Spark中的逻辑块。这些文件不是中介,因为Spark不会将它们合并到更大的分区文件中。由于Spark中的调度开销较小,因此映射器(M)和reducer(R)的数量远远高于Hadoop。因此,将M*R个文件发送到相应的Reducer可能会导致大量开销。

与Hadoop类似,Spark还提供参数spark.shuffle.compress来指定压缩映射输出的压缩库。在这种情况下,它可以是Snappy(默认情况下)或LZFSnappy仅为每个打开的文件使用33KB的缓冲区,并显着降低了遇到内存不足错误的风险。

reduce side 上,Spark要求所有混洗数据都适合相应reducer任务的内存,相反Hadoop可以选择将其溢出到磁盘。例如,这只会在reducer任务要求GroupByKeyReduceByKey操作的所有混洗数据的情况下发生。在这种情况下,Spark会抛出一个内存不足的异常,这对于开发人员来说已经证明是一个很大的挑战。

同样使用Spark,没有重叠的复制阶段,不像Hadoop具有重叠的复制阶段,即使在映射完成之前,映射器也会将数据推送到reducer。这意味着与Hadoop中的 push 操作相比,shuffle是Spark中的 pull 操作。每个reducer还应该维护一个网络缓冲区来获取map输出。此缓冲区的大小通过参数spark.reducer.maxMbInFlight指定(默认情况下为48MB)。

有关Apache Spark中 shuffling 的更多信息,我建议您阅读以下内容:

答案 1 :(得分:0)

只要数据需要在执行者(工作者节点)之间移动,就会发生