Java Hadoop - Reducer 在使用 Combiner 类时多次接收同一个键的不同值

标签 java hadoop key reduce

我在 Hadoop Java API (1.0.3) 中编写了一个 Map Reduce 作业。 这项工作包括对我的数据中特定字段 (X) 的所有值求和,并创建其他字段的加权分布。

输入:

1 field1_1 field2_1 field3_1 ... fieldX_1
2 field1_2 field2_2 field3_2 ... fieldX_2
3 field1_3 field2_3 field3_3 ... fieldX_3

由于我的数据中的任何行都会发出一对,并且我需要使用单个 reducer 来汇总所有值,因此我想将相同的 Reduce 类设置为 Combiner。

总 X 求和:

map 输出:

X fieldX_1
X fieldX_2 
X fieldX_3
X ... 

减少输出:

X fieldX_1+fieldX_2+fieldX_3+...

发生的奇怪事情是合并器/缩减器多次收到相同的 key :

X [fieldX_1 fieldX_1 fieldX_1 ... fieldX_1]
X [fieldX_2 fieldX_2 fieldX_2 ...]
X [fieldX_3 fieldX_3 fieldX_3 ...]
X ...

我很确定这一点,因为我正在记录所有传递给 reduce 方法的每次调用的 stderr 以进行调试。

我想添加一个更具体的例子:

数据:

1 field1_1 field2_1 field3_1 ... 10
2 field1_2 field2_2 field3_2 ... 20
3 field1_3 field2_3 field3_3 ... 30
4 field1_1 field2_1 field3_1 ... 10
5 field1_2 field2_2 field3_2 ... 40
6 field1_3 field2_3 field3_3 ... 20
...

map 输出:

X 10
X 20
X 30
X 10
X 40
X 20 

减少输入(使用组合器):

X [10 10 10 10]
X [20 20 20]
X [30 30 30 30 30 30 30]
X [40 40]

减少输出(使用组合器):

X 40
X 60
X 210
X 80

X 是常量标签(字段名)。 请注意,reducer 是使用相同的键 X 和相同的 X 值的集合调用的,例如[10 10 10 ...] 或 [30 30 30 ...]。 每个总和将单独输出。我的意思是算法工作正常,但在这个阶段需要一个额外的减少步骤来总结重复项。

真实日志示例:

Nov 06, 2013 8:50:12 AM MYCLASS logInputError
WARNING: REDUCE-INPUT: X,[10.0]
Nov 06, 2013 8:50:12 AM MYCLASS logOutputError
WARNING: REDUCE-OUTPUT: X,10.0
Nov 06, 2013 8:50:12 AM MYCLASS logInputError
WARNING: REDUCE-INPUT: X,[25.865, 25.865]
Nov 06, 2013 8:50:12 AM MYCLAS logOutputError
WARNING: REDUCE-OUTPUT: X,51.73
Nov 06, 2013 8:50:12 AM MYCLASS logInputError
WARNING: REDUCE-INPUT: X,[1449271.4, 1449271.4, 1449271.4, 1449271.4, 1449271.4, 1449271.4, 1449271.4, 1449271.4, 1449271.4, 1449271.4, 1449271.4, 1449271.4, 1449271.4, 1449271.4]
Nov 06, 2013 8:50:12 AM MYCLASS logOutputError
WARNING: REDUCE-OUTPUT: X,2.0289798E7
Nov 06, 2013 8:50:12 AM MYCLASS logInputError
WARNING: REDUCE-INPUT: X,[514994.53, 514994.53, 514994.53, 514994.53, 514994.53, 514994.53, 514994.53, 514994.53, 514994.53, 514994.53, 514994.53, 514994.53, 514994.53]
Nov 06, 2013 8:50:12 AM MYCLASS logOutputError
WARNING: REDUCE-OUTPUT: X,6694929.0
Nov 06, 2013 8:50:12 AM MYCLASS logInputError
WARNING: REDUCE-INPUT: X,[1438665.5, 1438665.5, 1438665.5, 1438665.5, 1438665.5, 1438665.5, 1438665.5, 1438665.5, 1438665.5, 1438665.5, 1438665.5, 1438665.5, 1438665.5]
Nov 06, 2013 8:50:12 AM MYCLASS logOutputError
WARNING: REDUCE-OUTPUT: X,1.8702654E7

如果我删除 Combiner,一切正常。 我知道 Combiner 可能会被调用 0 次、1 次或多次,但是 Reducer 呢?它应该只被调用一次,不是吗?

但更奇怪的是,我正在为字段分布重复类似的过程,而这只发生在 X 求和问题上......

加权场分布

map 输出(示例字段 1):

field1_1 X_1
field1_2 X_2
field1_3 X_3
... 

减少输出:

field1(class1) fieldX(class1)+fieldX(class1)+fieldX(class1)+...
field1(class2) fieldX(class2)+fieldX(class2)+fieldX(class2)+...
field1(class3) fieldX(class3)+fieldX(class3)+fieldX(class3)+...
...

基本上,对于 field1 的每个值,我将 fieldX 的所有关联值相加并对多个字段(field1、field2、field3...)重复相同的过程。

对于那些发出的对,reducer 接收单个键 (field1(class1)) 和值数组 ([fieldX(class1)...]),这应该是正常的行为。

结论

一个考虑因素是,对于 X 求和问题,单个键 (X) 映射的值数量等于数据的大小(行数)。同时,对于字段加权分布,值分布在该字段包含的几个类标签中。

这是我的代码中的错误还是我没有考虑到 Hadoop 的某些过程细节?

根据 M/R 范式,Reducer 类应该一次接收特定键的所有值,而不是分成更多的分区。

希望得到好的反馈。

最佳答案

The weird thing that happens is that the combiner receives the same key multiple times

这是可能的,因为组合器可能会被 MapReduce 框架多次调用,参见 JobConf#setCombinerClass() :

The framework may invoke the combiner 0, 1, or multiple times, in both the mapper and reducer tasks. In general, the combiner is called as the sort/merge result is written to disk. The combiner must:

  • be side-effect free
  • have the same input and output key types and the same input and output value types

关于Java Hadoop - Reducer 在使用 Combiner 类时多次接收同一个键的不同值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19589552/

相关文章:

java - GUI 更新可以在 IDE 中工作,但并不总是从 jar 文件中进行

java - JSON 到 Java 中的对象?

hadoop - Datanode处于死状态,因为使用的DFS为100%

hadoop - 如何处理 pig 中的重复代码(模块化)

java - 无法在 java 中获得与 Adob​​e 中的公钥显示相匹配的公钥显示

java - f :validateRequired does not work on Tomcat

java - 我如何转换这个字符串,它是java集合中的json响应?

python - Hadoop MapReduce 如何将字符串参数传递给 Mapper

C++:在不知道 key 的情况下插入 std::map

javascript - 如何使用 WebdriverIO 同时按下两个键?