引
MapReduce输出格式类图。
一. OutputFormat及其子类
1. OutputFormat类
本类主要用于描述输出数据的格式,它能够将用户提供的 key/value 对写入特定格式的文件中。主要涉及以下两个方法:
RecordWriter<K, V> getRecordWriter(TaskAttemptContext var1)
:根据TaskAttemptContext(map及reduce函数的参数Context对象间接继承自该类)对象中的相关信息返回一个RecordWriter()
对象(包含一个键值对数据)。后者负责键值对的写入操作。void checkOutputSpecs(JobContext var1)
:用于检测作业输出规范有效性。比如FileOutputFormat
中输出路径未设置、输出路径已存在时会抛出异常。该方法通常会在任务初始化阶段被调用。OutputCommitter getOutputCommitter(TaskAttemptContext var1)
:方法来负责确保输出被正确提交(待看)‘’
2. FileOutputFormat类
所有写入到文件系统的类都继承自该类,实现了一些公共方法。输入基类该类继承自OutputFormat
类,实现了以上最后两个方法。下面对一些常用方法进行总结。
setOutputPath(Job job, Path outputDir)
:设置输出路径。setCompressOutput(Job job, boolean compress)
:是否使用压缩算法压缩输出。setOutputCompressorClass(Job job, Class<? extends CompressionCodec> codecClass)
:设置压缩算法所使用的类。checkOutputSpecs(JobContext job)
:实现了OutputFormat
,该方法会在输出路径未设置、输出路径存在时抛出异常。getOutputCommitter(TaskAttemptContext var1)
:待看
其并未实现getRecordWriter()
方法,由其子类实现。
3. TextOutputFormat类
该类继承自FileOutputFormat
类,主要用途是将每条记录写为文本行。实现了getRecordWriter
方法。该方法会返回一个TextOutputFormat所定义的内部类LineRecordWriter来实现输出。类主要成员如下:
相关源码解析参见:http://blog.51cto.com/luchunli/1719174
TextOutputFormat类的每个键-值对由制表符进行分隔, 可通过mapreduce.output.textoutputformat.separator
属性改变默认的分隔符。可以使用NullWritable来省略输出的键或值。
4. NullOutputFormat类
该类相当于没有任何输出。根据其源码可以看出,其所有的方法均为空方法体。
5. SequenceFileOutFotmat类
该类负责将输出写为一个顺序文件,特别适合迭代式的MapReduce作业。
6. SequenceFileAsBinaryOutFotmat类
使用原始二进制格式将键值对写到一个顺序文件中。
7. MapFileOutputFormat类
使用mapfile作为输出格式。对于MapFile,其键必须有序。
二. RecordWriter类
该类源码如下,主要包含两个方法,见注释
public abstract class RecordWriter<K, V> {
public RecordWriter() {
}
# 将键值对数据写入输出路径
public abstract void write(K var1, V var2) throws IOException, InterruptedException;
# 关闭方法
public abstract void close(TaskAttemptContext var1) throws IOException, InterruptedException;
}
三. 多个输出
FileOutFormat及其子类产生的文件放在输出目录下。每个reduce一个文件并且文件由分区命名。MapReduce的MultipleOutputFormat类提供了对输出文件名的控制或让每个reduce产生多个文件。
1. 问题产生
针对一个数据集,我们需要通过MR作业为每一个气象站生成一个气象文件。
2. 解决方案
方案1:修改分区方式,设置reduce个数
此方法由如下的缺点:
- 需要在作业运行之前知道气象站的分区数和气象站个数,然而这时不现实的,也是不合理的
- 有的气象站数据量大,有的气象站数据量小。如果一个气象站配置一个reduce任务,既浪费资源,又无法保证时间。
- 使用这种方法相比系统默认的hash散列排序,会导致分区数少或不均匀。让很多的reduce做少量工作。
方案2:使用默认分区方式,使用MultipleOutput类
MultipleOutput类
此类允许将数据写入到多个文件中,其允许每个reduce或只有map作业的mapper创建多个文件。采用name-m-nnnnn形式的文件用于map输出,采用name-r-nnnnn形式的文件名用于reduce输出。
- name:程序设定名
- nnnnn:块号整数,保证不同分区mapper或reduce写的输出在相同名字情况下不会冲突。
四. 延迟输出
FileOutputFormat类在空文件时仍然会产生输出。我们可以使用LazyOutputFormat,当且仅当分区有数据是才产生输出。