我是Spark的新手,想了解MapReduce是如何在幕后完成的,以确保我正确使用它。这篇文章提供了一个很好的答案,但我的结果似乎没有遵循所描述的逻辑。我正在命令行上运行 Scala 中的 Spark 快速入门指南。当我正确地进行行长添加时,事情就会很好。总行长为 1213:
scala> val textFile = sc.textFile("README.md")
scala> val linesWithSpark = textFile.filter(line => line.contains("Spark"))
scala> val linesWithSparkLengths = linesWithSpark.map(s => s.length)
scala> linesWithSparkLengths.foreach(println)
Result:
14
78
73
42
68
17
62
45
76
64
54
74
84
29
136
77
77
73
70
scala> val totalLWSparkLength = linesWithSparkLengths.reduce((a,b) => a+b)
totalLWSparkLength: Int = 1213
当我稍微调整它以使用 (a-b) 而不是 (a+b) 时,
scala> val totalLWSparkTest = linesWithSparkLengths.reduce((a,b) => a-b)
根据这篇文章中的逻辑,我预计 -1185:
List(14,78,73,42,68,17,62,45,76,64,54,74,84,29,136,77,77,73,70).reduce( (x,y) => x - y )
Step 1 : op( 14, 78 ) will be the first evaluation.
x is 14 and y is 78. Result of x - y = -64.
Step 2: op( op( 14, 78 ), 73 )
x is op(14,78) = -64 and y = 73. Result of x - y = -137
Step 3: op( op( op( 14, 78 ), 73 ), 42)
x is op( op( 14, 78 ), 73 ) = -137 and y is 42. Result is -179.
...
Step 18: op( (... ), 73), 70) will be the final evaluation.
x is -1115 and y is 70. Result of x - y is -1185.
然而,奇怪的事情发生了:
scala> val totalLWSparkTest = linesWithSparkLengths.reduce((a,b) => a-b)
totalLWSparkTest: Int = 151
当我再次运行它时...
scala> val totalLWSparkTest = linesWithSparkLengths.reduce((a,b) => a-b)
totalLWSparkTest: Int = -151
谁能告诉我为什么结果是 151(或 -151)而不是 -1185?
发生这种情况是因为减法既不是关联也不是交换的。让我们从关联性开始:
(- (- (- 14 78) 73) 42)
(- (- -64 73) 42)
(- -137 42)
-179
与
(- (- 14 78) (- 73 42))
(- -64 (- 73 42))
(- -64 31)
-95
现在是交换的时候了:
(- (- (- 14 78) 73) 42) ;; From the previous example
与
(- (- (- 42 73) 78) 14)
(- (- -31 78) 14)
(- -109 14)
-123
Spark 首先对单个分区应用reduce
,然后按任意顺序合并部分结果。如果您使用的函数不满足一个或两个条件,则最终结果可能是不确定的。