一步一步学习hadoop(十二)
MapReduce作业输出
hadoop的输出格式和输入格式对应,都是实现类OutputFormat,按使用方式分为三种,文本格式,二进制格式,自定义文件输出(??Multiple outputs)。
1.文本格式
TextOutputFormat是Hadoop的默认输出格式,对应于KeyValueInputFormat,将键值对转化为文本,中间以分隔符(默认为\t)隔开,分隔符可以在作业设置时使用mapreduce.output.textoutputformat.separator属性设置。关于TextOutputFormat的key或者value,可以设置为NullWritable,表示key或者value不输出到输出文件中,如果两者都为NullWritable,则不输出内容,相当于NullOutputFormat。
2.二进制格式
hadoop中两个重要的二进制格式,一个是SequenceFile,一个是MapFile,这两种文件对MapReduce作业是非常好的文件保存方式,因为这两种格式非常容易压缩。
对应SequenceFile的是SequenceFileOutputFormat和SequenceFileAsBinaryOutputFormat,这两者的区别是前者直接保存键值对,后者将键值对转化为BytesWritable后在保存,即保存为二进制格式。
对应MapFile的是MapFileOutputFormat,由于MapFile的要求,在reducer中数据写入必须是保持键值是有序的。
3.自定义文件输出
默认情况下,输出文件的名称是以 part-r-00000, part-r-00001.....命名的,但有时我们想要使用自己的命名方式进行命名。
以一个API文档的事例说明
首先在作业设置中进行相应设置
Job job = new Job();
FileInputFormat.setInputPath(job, inDir);
FileOutputFormat.setOutputPath(job, outDir);
job.setMapperClass(MOMap.class);
job.setReducerClass(MOReduce.class);
...
// 对于文本输出格式增加额外的字符串text
MultipleOutputs.addNamedOutput(job, "text", TextOutputFormat.class,
LongWritable.class, Text.class);
// 对于SequenceFile输出格式增加额外的字符串seq
MultipleOutputs.addNamedOutput(job, "seq",
SequenceFileOutputFormat.class,
LongWritable.class, Text.class);
...
job.waitForCompletion(true);
然后在Reducer中
String generateFileName(K k, V v) {
return k.toString() + "_" + v.toString();
}
public class MOReduce extends
Reducer<WritableComparable, Writable,WritableComparable, Writable> {
private MultipleOutputs mos;
public void setup(Context context) {
...
mos = new MultipleOutputs(context);
}
public void reduce(WritableComparable key, Iterator<Writable> values,
Context context)
throws IOException {
...
mos.write("text", key, new Text("Hello"));
mos.write("seq", LongWritable(1), new Text("Bye"), "seq_a");
mos.write("seq", LongWritable(2), key, new Text("Chau"), "seq_b");
mos.write(key, new Text("value"), generateFileName(key, new Text("value")));
...
}
public void cleanup(Context) throws IOException {
mos.close();
...
}
}
4.其它
LazyOutputFormat,直到真正的写入时才创建文件。
DBOutputFormat,往数据库里写数据时使用
hadoop的输出格式和输入格式对应,都是实现类OutputFormat,按使用方式分为三种,文本格式,二进制格式,自定义文件输出(??Multiple outputs)。
1.文本格式
TextOutputFormat是Hadoop的默认输出格式,对应于KeyValueInputFormat,将键值对转化为文本,中间以分隔符(默认为\t)隔开,分隔符可以在作业设置时使用mapreduce.output.textoutputformat.separator属性设置。关于TextOutputFormat的key或者value,可以设置为NullWritable,表示key或者value不输出到输出文件中,如果两者都为NullWritable,则不输出内容,相当于NullOutputFormat。
2.二进制格式
hadoop中两个重要的二进制格式,一个是SequenceFile,一个是MapFile,这两种文件对MapReduce作业是非常好的文件保存方式,因为这两种格式非常容易压缩。
对应SequenceFile的是SequenceFileOutputFormat和SequenceFileAsBinaryOutputFormat,这两者的区别是前者直接保存键值对,后者将键值对转化为BytesWritable后在保存,即保存为二进制格式。
对应MapFile的是MapFileOutputFormat,由于MapFile的要求,在reducer中数据写入必须是保持键值是有序的。
3.自定义文件输出
默认情况下,输出文件的名称是以 part-r-00000, part-r-00001.....命名的,但有时我们想要使用自己的命名方式进行命名。
以一个API文档的事例说明
首先在作业设置中进行相应设置
Job job = new Job();
FileInputFormat.setInputPath(job, inDir);
FileOutputFormat.setOutputPath(job, outDir);
job.setMapperClass(MOMap.class);
job.setReducerClass(MOReduce.class);
...
// 对于文本输出格式增加额外的字符串text
MultipleOutputs.addNamedOutput(job, "text", TextOutputFormat.class,
LongWritable.class, Text.class);
// 对于SequenceFile输出格式增加额外的字符串seq
MultipleOutputs.addNamedOutput(job, "seq",
SequenceFileOutputFormat.class,
LongWritable.class, Text.class);
...
job.waitForCompletion(true);
然后在Reducer中
String generateFileName(K k, V v) {
return k.toString() + "_" + v.toString();
}
public class MOReduce extends
Reducer<WritableComparable, Writable,WritableComparable, Writable> {
private MultipleOutputs mos;
public void setup(Context context) {
...
mos = new MultipleOutputs(context);
}
public void reduce(WritableComparable key, Iterator<Writable> values,
Context context)
throws IOException {
...
mos.write("text", key, new Text("Hello"));
mos.write("seq", LongWritable(1), new Text("Bye"), "seq_a");
mos.write("seq", LongWritable(2), key, new Text("Chau"), "seq_b");
mos.write(key, new Text("value"), generateFileName(key, new Text("value")));
...
}
public void cleanup(Context) throws IOException {
mos.close();
...
}
}
4.其它
LazyOutputFormat,直到真正的写入时才创建文件。
DBOutputFormat,往数据库里写数据时使用