MapReduce的类型与格式

MapReduce类型

map函数和reduce函数常规格式:

map:(k1,v1)—>list(k2,v2)

reduce:(k2,list(v2))—>list(k3,v3)

如果含有combiner函数

map:(k1,v1)—>list(k2,v2)

combiner:(k2,list(v2))—>list(k2,v2)

reduce:(k2,list(v2))—>list(k3,v3)

当combiner函数和reduce函数一致时,k2与k3相同,v2与v3相同

partition函数对中间结果(k2,v2)进行处理,返回一个索引值,即分区号

partition:(k2,v2)—>integer

默认的MapReduce作业

                Configuration conf = getConf();
		//job对象指定作业执行的规范,控制整个作业的执行
		Job job = new Job(conf, "MaxTemperature");
		job.setJarByClass(MaxTemperature.class); 		//通过该类寻找作业执行的jar包
		FileInputFormat.addInputPath(job, new Path(arg0[1]));			//设置作业数据输入路径
		FileOutputFormat.setOutputPath(job, new Path(arg0[1]));	//设置作业执行结果输出路径
		
		job.setInputFormatClass(TextInputFormat.class); 				//默认输入格式,它产生的键类型是LongWritable,值类型是Text。这里影响的是K1,V1
		
		job.setMapperClass(Mapper.class);  										//默认的Mapper类,将输入原封不动的输出
		
		job.setMapOutputKeyClass(LongWritable.class);					//map的键输出类型,由上面的默认输入格式确定的。这里影响K2
		job.setMapOutputValueClass(Text.class);									//同上,这里影响V2
		
		job.setPartitionerClass(HashPartitioner.class); 						//默认分区函数HashPartitoner,对每条记录的键进行哈希操作,决定分区,
																										//每个分区对应着reduce任务。他是将键与最大整数做一次按位与操作然后对分区的个数(reduce个数)取模
		job.setCombinerClass(Reducer.class);  									//默认并不执行combiner函数,但是如果执行combiner函数,一般与reduce函数一致
		
		job.setNumReduceTasks(1); 														//默认情况只有一个reduce
		job.setReducerClass(Reducer.class);										//默认reduce函数是Reduce.class,他也是将输入原封不动的输出
		
		job.setOutputKeyClass(LongWritable.class); 							//输出键类型
		job.setOutputValueClass(Text.class); 										//输出值类型
		job.setOutputKeyClass(TextOutputFormat.class); 				//默认输出格式,将键和值转换成字符串,并且用制表符分割开,然后一行一条记录

输入格式



输入分片

一个输入分片(split)就是一个map操作处理的输入块,输入分片在java中表示为InputSplit接口:

public abstract class InputSpilt{
            public abstract long getLength();
            public abstract String[] getLoacations();
}

存储位置供mapreduce使用,以便使map任务尽量在分片附近。分片大小是用来对分片进行排序,以便优先处理最大的最大分片,从而最小化时间

InputSplit不需要MR开发人直接处理,而是由InputFormat创建。

客户端通过调用InputFormat的getSplits()计算分片,然后将他们送到application master(或jobtracker),am使用存储位置信息调度map任务在tasktracker上处理这些分片数据。map任务把输入分片传递给InputFormat的getRecordReader()方法来获得这个分片的RecordReader。RecordReader类似迭代器,对map任务进行迭代,来生成键/值对,然后传递给map函数。

运行作业多的客户端通过调用


FileInputFormat类

FileInputFormat是所有文件作为数据源的InputFormat的实现类,主要有两个功能:指定输入文件位置和输入文件生成分片的实现代码段。

FileInputFormat指定输入路径

addInputPath(Job job,Path path);

addInputPaths(Job job,String paths);

setInputPaths(Job job,Path ...inputPaths);

可以添加一个路径或者多个路径,其中setInputPaths是以此设定完成的路径列表。其中路径可以是一个文件、一个目录、或者一个glob(通配,通过通配符来获取路径),当路径是一个目录的时候表示包含目录下的所有文件。当目录中包含目录的时候,这个目录也会被解释称文件,所以会报错。可以通过使用一个文件glob或者一个过滤器根据命名模式限定选择目录中的文件。还可以通过设置属性mapred.input.dir.recursive为true强制对目录进行递归读取。如果需要排除目录中的个别文件,可以通过setInputPathFileter()设置一个过滤器来进行过滤,如果不设置过滤器,也会有默认的过滤器排除隐藏文件(以.和_开头的)。路径和过滤器业可以使用配置文件进行配置:mapred.input.dir和mapred.input.path.Fileter.class

小文件处理(小文件是指比HDFS块小很多)

在Hadoop中使用小文件的弊端:

(1)、增加map开销,因为每个分片都要执行一次map任务,map操作会造成额外的开销

(2)、MapReduce处理数据的最佳速度就是和集群中的传输速度相同,而处理小文件将增加作业的寻址次数

(3)、浪费namenode的内存

解决方法:

使用SequenceFile将这些小文件合并成一个大文件或多个大文件:将文件名作为键,文本内容作为值。

但是如果HDFS中已经存在的大批小文件,可以使用CombinerFileInputFormat。

CombinerFileInputFormat把多个文件打包成一个文件以便每个mapper能够处理更过的数据

避免切分

有时候不需要将文件进行切分,mapper完整处理每个输入文件。例如检查一个文件的所有记录是否有序。

可以通过设置最小分片大小大于要处理的文件。第二种就是使用FileInputFormat的具体子类,并且重载isSplitable()方法,把返回值设置为false。

mapper中的信息

通过调用Mapper中的Context的getInputSolit()返回一个InputSplit,如果使用的是FileInputFormat,则可以强转为FileSplit,然后用此访问正在输入文件的路径getPath(),分片开始处的字节偏移量,getLength()分片的长度。

TextInputFormat

文本输入是默认的InputFormat,每条记录是一行输入,键是LongWritable类型,存储该记录在整个文件的字节偏移量。值是该行的内容,不包括终止符(回车、换行等),它被打包成Text对象。

KeyValueTextInputFormat

当文件中的每一行是一个键/值对,使用某个分界符进行分割,如制表符。可以通过mapreduce.input.keyvaluelinerecordreader.key.value.seperator属性来指定分隔符。默认是一个制表符。其中这个键是分隔符前的文本,值是分隔符后的文本,其类型都是Text类型。如:

line1:this is line1 text

line2:this is line2 text

则被分为两条记录,分别是:

(line1,this is line1 text)

(line2,this is line2 text)

NLineInputFormat

在TextInputFormat和KeyValueTextInputFormat中,每个mapper收到的输入行数并不确定,行数取决于输入分片的大小和行的长度。如果希望mapper收到固定行数的输入,可以使用NLineInputFormat作为InputFormat。与TextInputFormat奕扬,键是文件中行的字节偏移量,值是行的内容。

N是每个mapper收到的输入行数,默认是1。可以通过mapreduce.input.lineinputformat.linespermap属性设置。如:

On the top of the Crumetty Tree

The Quangle Wangle sat,

But his face you could not see,

On account of his Beaver Hat.

当N为2的时候,每个输入分片包含两行。

(0,On the top of the Crumetty Tree)

(33,The Quangle Wangle sat,)

另一个mapper则收到后两行

(57,But his face you could not see,)

(89,On account of his Beaver Hat.)

StreamInputFormat

当解析XMl文件的时候可以使用StreamInputFormat,将stream.recordreader.class属性设置为org.apache.Hadoop.Streaming.StreamXmlRecordReader使用StreamXmlRecordReader类。具体实现(没用过)可以查看该类官方文档

SequenceFileInputFormat

Hadoop顺序文件格式存储二进制的键/值对的序列。当需要使用顺序文件作为MapReduce的输入时,应该使用SequenceFileInputFormat。键和值由顺序文件指定,只需要保证map输入的类型匹配。

SequenceFileAsTextInputFormat

SequenceFileAsTextInputFormat是SequenceFileInputFormat的变体,将顺序文件的键和值转化为Text对象。

SequenceFileAsBinaryInputFormat

SequenceFileAsBinaryInputFormat是SequenceFileInputFormat的一种变体,获取顺序文件的键和值作为二进制对象。

MutipleInputs

一个MapReduce作业可能由多个输入文件,但所有文件都由同一个InputFormat和同一个mapper来处理。但是数据格式却有所不同,需要对不同的数据集进行连接操作。可以使用MutipleInputs类处理

DBInputFormat

DBInputFormat用于使用JDBC从关系数据库中读取数据。需要注意在数据库中运行太多mapper读取数据,可能会使数据库受不了,所以一般使用DBInputFormat加载少量数据。可以现将数据导入到HDFS中,一般将关系性数据库中数据导入到HDFS中可以使用Sqoop

输出格式

TextOutputFormat

默认的输出模式TextOutputFormat,每条记录写为一行。键和值是任意的,因为TextOutputFormat都要将其toString()转换为字符串。键值默认使用制表符分割,可以使用mapreduce.output.textoutputformat.separator属性改变分割符

SequenceFileOutputFormat

将输出写为一个顺序文件,当输出需要作为后续的MapReduce输入的时候,这种输出非常合适,因为它格式紧凑,容易被压缩。

SequenceFileAsBinaryOutputFormat

SequenceFileAsBinaryOutputForamt与SequenceFileAsBinaryInputFormat对应,将输出的键和值作为二进制格式写到SequenceFile容器中。

MultipleOutputFormat

有时候可能需要将每个reduce输出多个文件,可以使用MutltipleOutputFormat。

LazyOutputFormat

延迟输出,他是封装输出格式,可以保证指定分区第一条记录输出时才真正创建文件。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值