Spark:reduce和reduceByKey

时间:2016-02-04 15:34:30

标签: scala apache-spark rdd reduce

在Spark的文档中,它说RDDs方法reduce需要一个关联的AND交换二进制函数。

但是,方法reduceByKey只需要一个关联二进制函数。

sc.textFile("file4kB", 4)

我做了一些测试,显然这是我得到的行为。为何如此区别?为什么reduceByKey确保二进制函数总是以某种顺序应用(以适应缺乏可交换性)reduce不存在?

示例,如果加载一些(小)文本有4个分区(最小):

val r = sc.textFile("file4k", 4)

然后:

r.reduce(_ + _)

返回一个字符串,其中的部分并不总是以相同的顺序,而是:

r.map(x => (1,x)).reduceByKey(_ + _).first

始终返回相同的字符串(其中所有内容的顺序与原始文件中的顺序相同)。

(我查看了r.glom,文件内容确实分布在4个分区上,没有空分区。)

2 个答案:

答案 0 :(得分:7)

就我而言,这是文档中的错误,您看到的结果只是偶然的。练习,other resources和一个简单的analysis of the code表明传递给reduceByKey的函数不仅应该是关联的,还应该是可交换的。

  • 练习 - 虽然看起来订单在本地模式下保留,但在群集上运行Spark(包括独立模式)时不再是这样。

  • 其他资源 - 引用Data Exploration Using Spark中的AmpCamp 3

      

    Spark中有一个名为reduceByKey的方便方法,用于此模式。请注意,reduceByKey的第二个参数确定要使用的reducer数。默认情况下,Spark假定reduce函数是可交换和关联的,并在映射器端应用组合器。

  • 代码 - reduceByKey使用combineByKeyWithClassTag实施,并创建ShuffledRDD。由于Spark在洗牌后不保证订单,因此恢复它的唯一方法是将部分元数据附加到部分缩减的记录中。据我所知,没有发生这样的事情。

在旁注[{1}},因为它在PySpark中实现,只能使用一个只能交换的函数。它当然只是一个实现的细节,而不是合同的一部分。

答案 1 :(得分:1)

根据代码文档,最近更新/更正。 (感谢@ zero323):

  

reduceByKey使用关联和可交换的reduce函数合并每个键的值。这也将在将结果发送到reducer之前在每个映射器上本地执行合并,类似于"组合器"在MapReduce。

所以实际上它实际上是一个像@ zero323这样的文档错误在他的回答中指出。

您可以查看以下指向代码的链接,以确保: