OReilly Hadoop,The Definitive Guide阅读笔记
7 Chapter. MapReuce Types and formats
MapReduce Types
map: (K1, V1) -> list(K2, V2)
reduce: (K2, list(V2)) -> list(K3, V3)
通常,Map的输入类型K1,V1与输出类型K2,V2是不一样的,但是Reduce的输入类型必须与Map的输出类型保持一致,Reduce的输入和输出类型也是不同的,跟Map一样。
用代码来表示就是:
public interface Mapper<K1, V1, K2, V2> extends JobConfigurable, Closeable{
void map(K1 key, V1 value, OutputCollector<K2, V2> output, Reporter reporter) throws IOException;
}
public interface Reducer<K2, V2, K3, V3> extends JobConfigurable, Closeable{
void reduce(K2 key, V2 value, OutputCollector<K3, V3> output, Reporter reporter) throws IOExcetion;
}
|
如果使用了Combiner,那么它的输入和输出类型都是K2,V2
map: (K1, V1) -> list(K2, V2)
combine: (K2, list(V2)) -> (K2, V2)
reduce: (K2, list(V2)) -> list(K3, V3)
设置输入输出类型的方法:参看该书P117的Configuration of MapReduce types图表,总结得非常好。
缺省的话,中间值的数据类型(就是Key和Value)与最终的Output的类型是一致的,也就是与setOutputxxxType()设置的类型保持一致。
默认的InputFormat是TextInputFormat.class,输出的分别是行号和该行的内容。
默认的OutputFormat是TextOutputformat.class,将Key,Value转换成字符串,以tab分隔,输出到文件。
Partition(一般是Hash)出来的数据块,每块对应一个Reducer,所以Hash的Size与Reducer的个数是相等的。不同Map的输出中相同Key的数据总是能被分配到同一个Reducer。
Input Formats
Split工作流程:
1.JobClient调用getSplit(),以MapNumber做一个hint,获取Input数据的信息(包括需要切分的块数,以及每个块的存储位置),然后将这些信息提交给JobTracker.
2.JobTracker根据从JobClient获取的信息,调度TaskTracker执行Map操作。
3.Jobtracker使用RecordReader中的方法,将分配给它的Split数据块切分成Records,每个Record生成一个对,提交给后续的Reducer进行处理。
FileInputFormat类只切分大于HDFS BlockSize的文件,默认是64MB。当然这个值是可以设置的。
FileInputFormat中的computeSplitSize()方法计算Split的大小。
Hadoop更适合于处理a small number of large files than a large number of small files。
因为过多的小文件需要更多的Map,这会大大降低程序性能。
FileInputForamt至少保证每个文件都有一个Mapper,可以使用CombineFileInputFormat来合并多个小文件,提高程序性能。
阅读(1686) | 评论(0) | 转发(0) |