我正在尝试使用scala计算每行的迭代次数 以下是我的意见:
1 vikram
2 sachin
3 shobit
4 alok
5 akul
5 akul
1 vikram
1 vikram
3 shobit
10 ashu
5 akul
1 vikram
2 sachin
7 vikram
现在我按如下方式创建2个单独的RDD。
val f1 = sc.textFile("hdfs:///path to above data file")
val m1 = f1.map( s => (s.split(" ")(0),1) ) //creating a tuple (key,1)
//now if i create a RDD as
val rd1 = m1.reduceByKey((a,b) => a+b )
rd1.collect().foreach(println)
//I get a proper output i.e (it gives correct output every time)
//output: (4,1) (2,2) (7,1) (5,3) (3,2) (1,4) (10,1)
//but if i create a RDD as
val rd2 = m1.reduceByKey((a,b) => a+1 )
rd2.collect().foreach(println)
//I get a inconsistent result i.e some times i get this (WRONG)
//output: (4,1) (2,2) (7,1) (5,2) (3,2) (1,2) (10,1)
//and sometimes I get this as output (CORRECT)
//output: (4,1) (2,2) (7,1) (5,3) (3,2) (1,4) (10,1)
我无法理解为什么会发生这种情况以及在哪里使用什么。我也尝试过将RDD创建为
val m2 = f1.map(s => (s,1))
val rd3 = m2.reduceByKey((a,b) => a+1 )
// Then also same issue occurs with a+1 but every thing works fine with a+b
答案 0 :(得分:7)
reduceByKey
假设传递的函数是可交换和关联(因为docs明确表示)。
而且 - 您的第一个功能(a, b) => a + b
是,但(a, b) => a+1
不是。
<强> WHY吗
首先,reduceByKey
将提供的函数应用于每个分区,然后应用于所有分区的组合结果。换句话说,b
并不总是1
,因此使用a+1
并不是正确的。
考虑以下场景 - 输入包含4条记录,分为两个分区:
(aa, 1)
(aa, 1)
(aa, 1)
(cc, 1)
此输入上的 reduceByKey(f)
可能计算如下:
val intermediate1 = f((aa, 1), (aa, 1))
val intermediate2 = f((aa, 1), (cc, 1))
val result = f(intermediate2, intermediate1)
现在,让我们按照f = (a, b) => a + b
val intermediate1 = f((aa, 1), (aa, 1)) // (aa, 2)
val intermediate2 = f((aa, 1), (cc, 1)) // (aa, 1), (cc, 1)
val result = f(intermediate2, intermediate1) // (aa, 3), (cc, 1)
使用f = (a, b) => a + 1
:
val intermediate1 = f((aa, 1), (bb, 1)) // (aa, 2)
val intermediate2 = f((aa, 1), (cc, 1)) // (aa, 1), (cc, 1)
// this is where it goes wrong:
val result = f(intermediate2, intermediate1) // (aa, 2), (cc, 1)
主要的是 - 中间计算的顺序没有得到保证,并且可能在执行之间发生变化,对于后一种非交换函数的情况,这意味着结果有时是错误的。
答案 1 :(得分:2)
函数(a,b)=&gt; (a + 1)在性质上不具有联想性。 联想法则说,
f(a ,f(b , c)) = f(f(a , b), c)
假设以下键:
a = (x, 1)
b = (x, 1)
c = (x, 1)
应用函数(a,b)=&gt; (a + 1)
f(a ,f(b , c)) = (x , 2)
但是,
f(f(a , b), c) = (x , 3)
因此,它不是关联的,不适用于reduceByKey。