Spark:reduce和reduceByKey之间的语义差异

Yve*_*rès 11 reduce scala apache-spark rdd

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

但是,该方法reduceByKey仅需要关联二进制函数.

sc.textFile("file4kB", 4)
Run Code Online (Sandbox Code Playgroud)

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

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

val r = sc.textFile("file4k", 4)
Run Code Online (Sandbox Code Playgroud)

然后:

r.reduce(_ + _)
Run Code Online (Sandbox Code Playgroud)

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

r.map(x => (1,x)).reduceByKey(_ + _).first
Run Code Online (Sandbox Code Playgroud)

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

(我检查过r.glom,文件内容确实分布在4个分区,没有空分区).

zer*_*323 7

就我而言,这是文档中的错误,您看到的结果只是偶然的.实践,其他资源对代码的简单分析表明,传递给它的函数reduceByKey不仅应该是关联的,而且应该是可交换的.

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

  • 其他资源-引用数据探索利用星火AmpCamp 3:

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

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

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

  • 我想补充一点,reduce是一个动作,将数据返回给驱动程序,而reduceByKey是一个转换,返回另一个RDD (3认同)