Mapreduce 合路器和减速器可以不同吗?

Mapreduce 合路器和减速器可以不同吗?,mapreduce,reducers,combiners,Mapreduce,Reducers,Combiners,在许多MapReduce程序中,我看到一个reducer也被用作组合器。我知道这是因为这些项目的特殊性质。但我想知道他们是否能有所不同 是的,它们当然可以不同,但我不认为你想使用不同的类,因为大多数情况下你会得到意想不到的结果 组合器只能用于可交换(a.b=b.a)和结合{a.(b.c)=(a.b).c}的函数。这也意味着组合器可能只对键和值的子集进行操作,或者根本不执行,但您仍然希望程序的输出保持不变 选择具有不同逻辑的不同类可能不会给您提供逻辑输出。是的,合并器可能与Reducer不同,尽管

在许多MapReduce程序中,我看到一个reducer也被用作组合器。我知道这是因为这些项目的特殊性质。但我想知道他们是否能有所不同

是的,它们当然可以不同,但我不认为你想使用不同的类,因为大多数情况下你会得到意想不到的结果

组合器只能用于可交换(a.b=b.a)和结合{a.(b.c)=(a.b).c}的函数。这也意味着组合器可能只对键和值的子集进行操作,或者根本不执行,但您仍然希望程序的输出保持不变


选择具有不同逻辑的不同类可能不会给您提供逻辑输出。

是的,合并器可能与Reducer不同,尽管您的合并器仍将实现Reducer接口。组合器只能在特定情况下使用,这些情况将取决于作业。组合器将像一个减缩器一样工作,但只对每个映射器输出的键/值的子集进行操作


与减缩器不同,组合器将具有的一个约束是输入/输出键和值类型必须与映射器的输出类型匹配。

组合器的主要目标是优化/最小化将生成的键值对的数量 可以在映射器和还原器之间通过网络进行洗牌,从而保存为 尽可能地增加带宽

组合器的经验法则是它必须具有相同的输入和输出变量类型,原因是 因此,不能保证组合器的使用,它可以使用也可以不使用,具体取决于音量 以及泄漏的数量

当减速器满足此规则(即相同的输入和输出)时,可将其用作组合器 变量类型

combiner的另一个最重要的规则是,它只能在需要函数时使用 应用是交换的和结合的。类似于添加数字。但不类似于平均值(如果u r使用与减速机相同的代码)

现在回答你的问题,是的,当然它们可以不同,当你的减速机有不同类型的输入和输出变量时,你别无选择,只能复制你的减速机代码并修改它


如果您关心reducer的逻辑,您也可以以不同的方式实现,比如在组合器的情况下,您可以使用一个collection对象来拥有一个本地缓冲区,其中包含所有到达组合器的值,这比在reducer中使用它的风险要小,因为在reducer的情况下,它比组合器中的内存更容易耗尽。其他逻辑差异肯定存在,而且确实存在

这里是实现,您可以不使用combiner和使用combiner运行,两者给出完全相同的答案。在这里,减速器和合路器具有不同的动机和不同的实现方式

package combiner;

import java.io.IOException;


import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;

public class Map extends Mapper<LongWritable, Text, Text, Average> {

Text name = new Text();
String[] row;

protected void map(LongWritable offSet, Text line, Context context) throws IOException, InterruptedException {
    row = line.toString().split(" ");
    System.out.println("Key "+row[0]+"Value "+row[1]);
    name.set(row[0]);
    context.write(name, new Average(Integer.parseInt(row[1].toString()), 1));
}}
组合器类

public class Combine extends Reducer<Text, Average, Text, Average>{

protected void reduce(Text name, Iterable<Average> val, Context context)throws IOException, InterruptedException {
    int total=0; int count=0; long avg=0;

    for (Average value : val){
        total+=value.number;
        count+=1;
        avg=total/count;    
        }
    context.write(name, new Average(avg, count));

}
}
公共类{
受保护的void reduce(文本名,Iterable


请留下您的建议。

合路器可以被描述为本地减速器吗?在这个链接中,这是非常有用的东西。它解释了您应该何时使用合路器
public class Average implements Writable {

long number;
int count;

public Average() {super();}

public Average(long number, int count) {
    this.number = number;
    this.count = count;
}

public long getNumber() {return number;}
public void setNumber(long number) {this.number = number;}
public int getCount() {return count;}
public void setCount(int count) {this.count = count;}

@Override
public void readFields(DataInput dataInput) throws IOException {
    number = WritableUtils.readVLong(dataInput);
    count = WritableUtils.readVInt(dataInput);      
}

@Override
public void write(DataOutput dataOutput) throws IOException {
    WritableUtils.writeVLong(dataOutput, number);
    WritableUtils.writeVInt(dataOutput, count);

}
}
public class Combine extends Reducer<Text, Average, Text, Average>{

protected void reduce(Text name, Iterable<Average> val, Context context)throws IOException, InterruptedException {
    int total=0; int count=0; long avg=0;

    for (Average value : val){
        total+=value.number;
        count+=1;
        avg=total/count;    
        }
    context.write(name, new Average(avg, count));

}
}
public class Driver1 {

public static void main(String[] args) throws Exception { 

    Configuration conf = new Configuration();
    if (args.length != 2) {
        System.err.println("Usage: SecondarySort <in> <out>");
        System.exit(2);
    }
    Job job = new Job(conf, "CustomCobiner");
    job.setJarByClass(Driver1.class);
    job.setMapperClass(Map.class);
    job.setCombinerClass(Combine.class);
    job.setMapOutputKeyClass(Text.class);
    job.setMapOutputValueClass(Average.class);
    job.setReducerClass(Reduce.class);
    job.setOutputKeyClass(Text.class);
    job.setOutputValueClass(IntWritable.class);     
    FileInputFormat.addInputPath(job, new Path(args[0]));
    FileOutputFormat.setOutputPath(job, new Path(args[1]));
    System.exit(job.waitForCompletion(true) ? 0 : 1);
}
}