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

两个相等的组合键不能到达同一个减速器

惠文彬
2023-03-14

我正在用MapReduce框架用Java制作一个Hadoop应用程序。

对于输入和输出,我只使用文本键和值。在减少到最终输出之前,我使用一个合并器来做额外的计算。

但我有一个问题,钥匙不去同一个减速器。我在组合器中创建和添加了这样的键/值对:

public static class Step4Combiner extends Reducer<Text,Text,Text,Text> {
    private static Text key0 = new Text();
    private static Text key1 = new Text();

        public void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {
                key0.set("KeyOne");
                key1.set("KeyTwo");
                context.write(key0, new Text("some value"));
                context.write(key1, new Text("some other value"));
        }

}   

public static class Step4Reducer extends Reducer<Text,Text,Text,Text> {

            public void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {
                System.out.print("Key:" + key.toString() + " Value: ");
                String theOutput = "";
                for (Text val : values) {
                    System.out.print("," + val);
                }
                System.out.print("\n");

                context.write(key, new Text(theOutput));
            }

}

基本上,我创建的工作如下:

Configuration conf = new Configuration();
String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();

Job job4 = new Job(conf, "Step 4");
job4.setJarByClass(Step4.class);

job4.setMapperClass(Step4.Step4Mapper.class);
job4.setCombinerClass(Step4.Step4Combiner.class);
job4.setReducerClass(Step4.Step4Reducer.class);

job4.setInputFormatClass(TextInputFormat.class);
job4.setOutputKeyClass(Text.class);
job4.setOutputValueClass(Text.class);

FileInputFormat.addInputPath(job4, new Path(outputPath));
FileOutputFormat.setOutputPath(job4, new Path(finalOutputPath));            

System.exit(job4.waitForCompletion(true) ? 0 : 1);

减速机打印的标准输出如下:

Key:KeyOne Value: ,some value
Key:KeyTwo Value: ,some other value
Key:KeyOne Value: ,some value
Key:KeyTwo Value: ,some other value
Key:KeyOne Value: ,some value
Key:KeyTwo Value: ,some other value

这是没有意义的,因为键是相同的,因此它应该是2个还原器,其中3个值是相同的

希望你能帮我弄清这件事:)

共有2个答案

邹玮
2023-03-14

请在组合器中尝试以下操作:

context.write(new Text("KeyOne"), new Text("some value"));
context.write(new Text("KeyTwo"), new Text("some other value"));

我看到这种情况发生的唯一方法是,如果一个组合器中的key0不等于另一个组合器中的key0。我不确定如果键指向完全相同的实例,它会如何表现(如果您将键设为静态,则会发生这种情况)。

葛学民
2023-03-14

这很可能是因为您的组合器同时在映射和化简阶段运行(一个鲜为人知的“功能”)。

基本上,您正在修改组合器中的键,当映射输出在化简器中合并在一起时,该键可能会运行,也可能不会运行。在运行组合器(reduce side)后,键通过分组比较器馈送,以确定迭代传递给 reduce 方法的回值(我在这里绕过简化阶段的流方面 - 可迭代对象没有一组或值列表支持,如果分组比较器破坏了当前键和最后一个键相同,则对迭代器的更多调用().next()返回 true)

你可以尝试通过检查上下文来检测当前的组合器相位侧(映射或减少)(有一个 Context.getTaskAttempt().isMap() 方法,但我有一些记忆,这也存在一些问题,甚至可能在某个地方有一个关于此的JIRA票证)。

底线是,不要修改组合器中的键,除非你能找到绕过这个行为的方法,如果组合器运行在reduce端的话。

编辑以便调查@Amar的评论,我将一些代码(pastebin链接)放在一起,其中添加了一些详细的比较器、组合器、还原器等。如果您运行单个映射作业,则在还原阶段,不会运行任何组合器,并且映射输出将不会再次排序,因为它已经假定已排序。

假设在发送到组合器类之前对其进行排序,并且假设键将原封不动地出来-因此仍然是排序的。请记住,组合器旨在组合给定键的值。

因此,对于单个映射和给定的组合器,还原器以键一、键二、键一、键二、键二的顺序查看键。分组比较器看到它们之间的转换,因此您得到了对reduce函数的6个调用

如果使用两个映射器,则缩减器知道它有两个已排序的段(每个映射一个),因此在缩减之前仍然需要对它们进行排序-但由于段的数量低于阈值,因此排序是作为内联流排序完成的(同样,假定段已排序)。两个映射器的输出仍然是错误的(减少阶段的10条记录输出)。

因此,同样,不要修改合并器中的密钥,这不是合并器的用途。

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

  • 问题内容: 我在这里浏览了一些问题,但这些问题似乎都不是我的问题。假设我有2个字典,它们是dict1 和字典2 我正在编写一个程序,需要将它们结合到一个字典finaldict中 非常感谢您的帮助,我一直在努力,现在已经一无所获 问题答案: 这是通用版本。即使只有键之一存在键,也可以用它来创建一个以值作为列表的字典。 输出量 如果您使用的是Python 2,则必须像这样更改for循环:

  • 在一个表中有两列可以是来自同一表的外键,这样可以吗? 例如: 我有一个“address”表,表中有列: id,street,city_id,state,country(或id,street,city_id,state_id,state_id) 我有一个'states'表,保存状态和国家:id、name、level 那么我可以把states_id放在地址表的state和country中吗(如上面的括

  • key2值2 ... 文件2: 我让映射写键,值用一个字符预先说明它来自file1或file2,但不确定如何编写reduce阶段 我的map方法是

  • 问题内容: 我有以下两个玩具字典 我想得到一个唯一的字典,在其中我将第二个字典值堆叠在第一个字典之后,并放在相同的方括号内。 我尝试了以下代码 但是我获得的输出在每个键的列表中有两个列表,即 而我想获得 如何使用一行或两行代码来实现? 问题答案: 您几乎拥有了它,而是使用了附加两个列表的方法:

  • 问题内容: 我正在尝试将以下两个数组合并为一个共享相同密钥的数组: 第一个数组: 第二个数组: 如您所见,它们共享相同的密钥(Camera1,Camera2,Camera3等。) 这是我尝试过的: 问题答案: 理想情况下,我希望以一种方式格式化两个数组,从而简单地合并两个数组而不必大惊小怪。 但是我确实提出了一个使用过的解决方案。 输出为: