当前位置: 首页 > 知识库问答 >
问题:

JavaHadoop-当使用组合器类时,减少器多次接收同一键的不同值

左劲
2023-03-14

我在HadoopJavaAPI(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

由于我的数据中的任何一行都发出一对,并且我需要使用单个减法器来求和所有值,因此我想将相同的Reduce类设置为组合器。

总计 X 求和:

地图输出:

X fieldX_1
X fieldX_2 
X fieldX_3
X ... 

减少输出:

X fieldX_1+fieldX_2+fieldX_3+...

奇怪的是,合并器/缩减器会多次收到相同的密钥:

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

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

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

数据:

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
...

地图输出:

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 是一个常量标签(字段名称)。请注意,使用相同的键 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

如果我删除合并器,一切正常。我知道合并器可能被调用0次,1次或多次,但是减速器呢?它应该只被调用一次,不是吗?

但更奇怪的是,我对场分布重复了一个类似的过程,这仅发生在X求和问题上...

加权场分布

地图输出(示例字段 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 类应一次接收特定键的所有值,而不是划分为多个分区。

希望收到良好的反馈。

共有1个答案

柯苗宣
2023-03-14

奇怪的是,合并器会多次收到同一个密钥

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

在映射器和缩减器任务中,框架可以调用组合器0次、1次或多次。通常,当排序/合并结果写入磁盘时,会调用合并器。组合器必须:

  • 无副作用。
  • 输入和输出键类型相同,输入和输出值类型相同
 类似资料:
  • 我正在用MapReduce框架用Java制作一个Hadoop应用程序。 对于输入和输出,我只使用文本键和值。在减少到最终输出之前,我使用一个合并器来做额外的计算。 但我有一个问题,钥匙不去同一个减速器。我在组合器中创建和添加了这样的键/值对: 基本上,我创建的工作如下: 减速机打印的标准输出如下: 这是没有意义的,因为键是相同的,因此它应该是2个还原器,其中3个值是相同的 希望你能帮我弄清这件事:

  • 我有一个简单的地图减少工作,我正在建立反向索引。 我的映射器工作正常(我检查过了),并输出了word和docID:TFIDF值的密钥对: 映射器(仅显示输出): 化简器的唯一工作是组合这些值。这是我的实现: 然而,它没有组合任何东西,输出看起来基本上与来自映射器的相同。输出中有一些行具有相同的键,尽管reducer应该将它们组合起来——基本上,使用reducer时,输出文件中的所有键都应该是唯一的

  • 每个Hadoop开发者都知道合并器是优化mapreduce的关键,但它是可选的。它可以最小化带宽并提高mapreduce作业性能。在这里,我的问题是,hadoop在默认情况下提供了许多功能,如数据局部性问题,但没有将组合器作为默认值。为什么?这意味着在所有情况下合并器都是不可取的?当我们不使用合成器时。如果我将它设为默认值,会有什么问题呢?

  • 我有一条这样的小溪和两个水槽,但一次只使用一个: 或 我们使用哪个接收器是可配置的,但是如果我并行使用两个接收器怎么办?我该怎么做? 我想到了水槽。合并,但它也需要合并策略,我不想以任何方式合并这些汇的结果。我真的不关心它们,所以我只想通过HTTP将相同的数据发送到某个endpoint,同时将它们发送到数据库。Sink combine与broadcast非常相似,但从头开始实现广播会降低代码的可读

  • 问题内容: 我有两张桌子和。 第一台具有与第二表有田,, 我想要一个帐户进行多少次子请求以及他进行了多少次抓取的计数(基于,如果该帐户中填充了他的) 在一个查询中 输出: 问题答案: 使用类似 诀窍是使用表两次:和,每次由不同的字段联接。 关于效率的注意事项:我不确定,但是我相信这个解决方案比子查询解决方案要快,尽管没有对其进行测试(至少不会慢一些)。只要有可能,我总是更喜欢子查询。

  • 当我多次调用同一个函数时,每次都传递了不同的参数,我会这样做: 有没有更方便的方法做到这一点呢?