在很多MapReduce程序,我看到正在使用的减压器中的组合为好。 我知道这是因为这些程序的具体性质。 但我想知道,如果他们可以是不同的。
Answer 1:
是的,一个组合可以是减速器不同,虽然你合仍然会实现减速接口。 组合只能在将要与作业相关的特定情况下才能使用。 该组合将经营就像一个减速,但只从每个映射器输出的键/值的子集。
你合将有一个约束,不像减速,是输入/输出键和值的类型必须与输出类型的映射相匹配。
Answer 2:
是的,他们当然可以是不同的,但我不认为你需要使用不同的类作为主要你会得到意想不到的结果。
组合器只能在其是可交换的功能(AB = BA)和缔合{一个。(BC)=(AB).C}使用。 这也意味着,组合可以在你的钥匙和值的子集,只经营或可能根本不会执行,还是你想要的程序的输出保持不变。
选择具有不同的逻辑不同的类可能不会给你一个逻辑输出。
Answer 3:
下面是实现,您可以在不合并与合并运行,既提供了完全相同的答案。 这里减速,合路器有不同的动机和不同的实现。
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 Reduce extends Reducer<Text, Average, Text, LongWritable> {
LongWritable avg =new LongWritable();
protected void reduce(Text key, Iterable<Average> val, Context context)throws IOException, InterruptedException {
int total=0; int count=0; long avgg=0;
for (Average value : val){
total+=value.number*value.count;
count+=value.count;
avgg=total/count;
}
avg.set(avgg);
context.write(key, avg);
}
}
MapObject的类
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);
}
}
从Git的代码在这里
离开乌拉圭回合的建议..
Answer 4:
组合的主要目标是优化/最小化,将跨越映射器和减速器,从而保存为最带宽尽可能之间的网络进行改组密钥值对的数量。
组合器的经验法则是它必须有相同的输入和输出变量的类型,这种情况的原因,是组合使用不能保证,它可以或不可以被使用,这取决于泄漏的体积和数量。
当满足该规则,即相同的输入和输出变量的类型的减速器可被用作一个组合器。
用于合成其他最重要的规则是,当你要应用功能既可交换并且关联,它只能使用。 像。但不万一像平均添加数字(如果使用乌尔相同的代码作为减速机)。
现在回答你的问题,是关当然也可以是不同的,当你的减速机具有不同类型的输入和输出变量,U别无选择,而是为了使乌尔减速机代码并修改它不同的副本。
如果乌拉圭回合关心减速的逻辑,你可以以不同的方式为落实好,在组合的情况下,说你可以有一个集合对象有来组合的所有值的本地缓存,这是少风险比减速器使用它,因为在减速的情况下,更容易走出去的内存比组合。 其他逻辑差别当然可以存在并执行。