1.目的

   Mapreduce中关于文件的输入和结果的输出是一个重要的部分,而我们明白文件的类型和格式是很多种的,如:文件、二进制文件、数据库文件等等,通过学习明白Hadoop的Mapreduce如何处理各种类型和格式文件的输入和相应结果的输出。

2.内容

    1)Maprecude的类型

      一般来说,map和reduce函数遵循如下格式:

    map:(K1,V1)---->list(K2,V2)

    reduce:(K2,list(V2))---->list(K3,V3)

    通常,map的输入的键/值的类型(K1,V1)不同于输出类型(K2,V2),尽管reduce的输入类型要和map的输出类型相等,但是reduce的输出类型却没有类似的限制。

   默认的输入格式类型是TextInputFormat,它产生的键类型是LongWriteable类型,值类型是Text。

  选择reduce的个数:reducer的最优个数与集群中可用的reducer任务槽相关,总槽数由集群中节点的个数和每个节点任务槽数相乘所得。一个常用的方式是设置比总槽数少一点的reducer数,这样会给reducer任务留有余地(容忍一些错误而不导致作业执行时间延长),如果reduce任务很大,比较明智的做法是使用更多的reducer,使任务粒度更小,这样任务的失败才不至于显著的影响作业执行的时间。

    2)输入格式

     从一般的文本到数据库,hadoop可以处理很多种不同类型的数据格式。

     输入分片与记录:一个输入分片就是一个map处理的输入块,每个分片被拆分为若干记录,每条记录就是一个键/值对,map一条接一条的处理记录,其中每一个map操作只能处理一个分片。

    小文件与CombineFileInputFormat:相对于大批量的小文件,hadoop更适合处理少量的大文件。一个原因就是FileInputFormat生产的InputSplit是一个文件或者该文件的一部分,如果文件很小,并且数量很多,那么每次map只处理少量的输入数据,一个文件就会有很多的map任务,每次Map操作都会造成额外的开销。不过CombineFileInputFormat可以缓解这个问题,它把多个小文件打包成一个大文件,更关键的是那些块放入同一个分片时,CombineFileInputFormat会考虑机架和节点的因素,因此典型的Maprecude在输入数据时效率不会降低。

     避免切分:有两种方法可以避免切分,第一种就是增加最小分片的大小,使其值大于要处理文件的大小,尽管这种方法不是很漂亮。第二种方法便是使用FileInputFormat具体子类,并且重载isSplitable()方法,把返回值设置为false。列入一下就是一个不可分割的列子:

public class NonSplitableTextInputFileFormat extends TextInputFileFormat{
 protected boolean isSplitable(FileSystem fs, Path p)
{
   return false;
}

}

     二进制的输入:SequenceFileInputFormat,以顺序方式存在二进制格式的序列。

    数据库的输入和输出:DBInputFormat用于使用JDBC从关系型数据库中读取数据,因为它没有共享能力,所以访问的时候要特别小心。在运行太多的mapper的数据库中读取数据可以导致数据库受不了。因此DBInputFormat最好用于加载小量的数据,如果要与HDFS进行大数据的连接最好用MutiPileInputs。另一种方式是使用Sqoop。

    3)输出格式

     文本输出:默认的输出格式是TextOutputFormat,它把每条记录写成文本行。

     二进制输出:SequenceFileOutputFormat格式,将记录写成一个顺序文件。

    多个输出:MutiPileFileOutputFromat类可以将记录写入到多个文件,这些文件的名称取决于输出的键/值。