在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个分区上,没有空分区。)
答案 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这样的文档错误在他的回答中指出。
您可以查看以下指向代码的链接,以确保: