MapReduce中InputFormat和InputSplit解读
Hadoop的Mapreduce是一个分布并行处理大数据的程序框架,一个Map/Reduce作业(job)通常会把指定要处理(在job的配置中由我们来指定)数据集切分为若干独立的数据块(这个工作由mapreduce计算框架自动去完成),然后再由 map任务(task)以完全并行的方式处理它们。
MapReduce(job)要操作的数据保存在文件系统HDFS上,InputFormat接口定义的方法就是如何读取文件和分割文件以提供分片给mapper,TextInputFormat文本格式输入是InputFormat的默认实现类。
通过使用InputFormat,MapReduce框架可以做到:
1. 验证作业的输入的正确性;
2.把输入文件切分成多个逻辑InputSplits,并把每一个InputSplit分别分发给一个单独的MapperTask;
3.提供RecordReader的实现,这个RecordReader从指定的InputSplit中正确读出一条一条的K-V对,这些K-V对将由我们写的Mapper方法处理。
详细解读:
(1)InputFormat和InputSplit
InputSplit是Hadoop定义的用来传送给每个单独的map的数据,InputSplit存储的并非数据本身,而是一个分片长度和一个记录数据位置的数组。生成InputSplit的方法可以通过InputFormat()来设置。
当数据传送给map时,map会将输入分片传送到InputFormat,InputFormat则调用方法getRecordReader()生成RecordReader,RecordReader再通过creatKey()、creatValue()方法创建可供map处理的一个一个的<key,value>对。简而言之,InputFormat()方法是用来生成可供map处理的<key,value>对的。
Hadoop预定义了多种方法将不同类型的输入数据转化为map能够处理的<key,value>对,它们都继承自InputFormat,分别是:
InputFormat
|
|---BaileyBorweinPlouffe.BbpInputFormat
|---ComposableInputFormat
|---CompositeInputFormat
|---DBInputFormat
|---DistSum.Machine.AbstractInputFormat
|---FileInputFormat
|---CombineFileInputFormat
|---KeyValueTextInputFormat
|---NLineInputFormat
|---SequenceFileInputFormat
|---TeraInputFormat
|---TextInputFormat
其中TextInputFormat是Hadoop默认的输入方法,在TextInputFormat中,每个文件(或其一部分)都会单独地作为map的输入,而这个是继承自FileInputFormat的。
之后,每行数据都会生成一条记录,每条记录则表示成<key,value>形式:
· key值是每个数据的记录在数据分片中字节偏移量,数据类型是LongWritable;
value值是每行的内容,数据类型是Text。
注:
1.在写MapReduce程序的时候,我们写的***Mapper方法都要继承API提供的Mapper类:
通常我们会重写map()方法,map()每次接受一个K-V对,然后我们对这个K-V对进行处理,再分发出处理后的数据。
我们也可能重写setup()以对这个map task进行一些预处理,比如创建一个List之类的;
我们也可能重写cleanup()方法对做一些处理后的工作,当然我们也可能在cleanup()中写出K-V对。
举个例子就是:InputSplit的数据是一些整数,然后我们要在mapper中算出它们的和。我们就可以在先设置个sum属性,然后map()函数处理一个K-V对就是将其加到sum上,最后在cleanup()函数中调用context.write(key,value);
最后我们看看Mapper类中的run()方法,它相当于map task的驱动,我们可以看到run()方法首先调用setup()进行初始操作,然后对每个context.nextKeyValue()获取的K-V对,就调用map()函数进行处理,最后调用cleanup()做最后的处理。
2. 事实上,从context.nextKeyValue()就是调用了相应的RecordReader来获取K-V对的。
RecordReader:是用来从一个输入分片inputSplit中读取一个一个的K -V 对的抽象类,我们可以将其看作是在InputSplit上的迭代器。最主要的方法就是nextKeyvalue()方法,由它获取分片上的下一个K-V 对。
(2)OutputFormat
每一种输入格式都有一种输出格式与其对应。默认的输出格式是 TextOutputFormat ,这种输出方式与输入类似,会将每条记录以一行的形式存入文本文件。不过,它的键和值可以是任意形式的,因为程序内容会调用toString()方法将键和值转换为String类型再输出。
更多解读:《[Hadoop源码解读](一)MapReduce篇之InputFormat》
《[Hadoop源码解读](二)MapReduce篇之Mapper类》
《 [Hadoop源码解读](三)MapReduce篇之Job类 》