Hadoop中的setOutputKeyClass和setOutputValueClass

来源:互联网 发布:红颜知已的图片 编辑:程序博客网 时间:2024/06/18 06:43

mapreduce的数据流如下:

Mapper<K1, V1, K2, V2> --> Reducer<K2, V2, K3, V3>

setOutputKeyClass和setOutputValueClass是同时设置K2,V2和K3,V3的类型,也就是说以下代码:

job.setOutputKeyClass(Text.class);job.setOutputValueClass(IntWritable.class);

以上代码设置的是map输出的类型是Text,IntWritable,同时reduce的输出类型也是Text,IntWritable,因此,这里就存在问题了,当map和reduce输出的类型不一致的时候,就不能用这两个方法来设置了,讨论如下:
1)当K2, V2 和K3 , V3类型一致时
这时候就可以用下面的代码来设置map和reduce的输出类型

job.setOutputKeyClass(Text.class);job.setOutputValueClass(IntWritable.class);

而且还可以使用下面的语句

job.setCombinerClass();

2)当K2, V2 和K3 , V3类型不一致时(大多数情况)
这个时候就再用

job.setOutputKeyClass(Text.class);job.setOutputValueClass(IntWritable.class);

来设置就会报错,假如K2, V2类型为Text,Text而K3, V3类型为Text,IntWritable,那么就会报错,报错情况如下:

Caused by: java.io.IOException: wrong value class: class org.apache.hadoop.io.IntWritable is not class org.apache.hadoop.io.Text    at org.apache.hadoop.mapred.IFile$Writer.append(IFile.java:194)    at org.apache.hadoop.mapred.Task$CombineOutputCollector.collect(Task.java:1313)    at org.apache.hadoop.mapred.Task$NewCombinerRunner$OutputConverter.write(Task.java:1630)    at org.apache.hadoop.mapreduce.task.TaskInputOutputContextImpl.write(TaskInputOutputContextImpl.java:89)    at org.apache.hadoop.mapreduce.lib.reduce.WrappedReducer$Context.write(WrappedReducer.java:105)    at hadoop.MyJob$Reduce.reduce(MyJob.java:65)    at hadoop.MyJob$Reduce.reduce(MyJob.java:1)    at org.apache.hadoop.mapreduce.Reducer.run(Reducer.java:171)    at org.apache.hadoop.mapred.Task$NewCombinerRunner.combine(Task.java:1651)    at org.apache.hadoop.mapred.MapTask$MapOutputBuffer.sortAndSpill(MapTask.java:1630)    at org.apache.hadoop.mapred.MapTask$MapOutputBuffer.access$900(MapTask.java:873)    at org.apache.hadoop.mapred.MapTask$MapOutputBuffer$SpillThread.run(MapTask.java:1525)2017-09-13 14:23:34,963 INFO [org.apache.hadoop.mapred.LocalJobRunner] - map task executor complete.2017-09-13 14:23:35,028 WARN [org.apache.hadoop.mapred.LocalJobRunner] - job_local78442734_0001java.lang.Exception: java.io.IOException: Spill failed

上面第一行可以看到,报错,IntWritable不是Text类型,说明setOutputKeyClass和setOutputValueClass默认是同时设置map和reduce的输出类型的

解决办法:
当K2, V2 和K3 , V3类型不一致时,我们需要用setMapOutputKeyClass和setMapOutputValueClass来设置map的输出类型。仍以K2, V2类型为Text,Text而K3, V3类型为Text,IntWritable为例,设置如下:

job.setOutputKeyClass(Text.class);job.setOutputValueClass(IntWritable.class);job.setMapOutputKeyClass(Text.class);job.setMapOutputValueClass(Text.class);

setMapOutputKeyClass和setMapOutputValueClass会覆盖setOutputKeyClass和setOutputValueClass设置的效果,这样一来,setMapOutputKeyClass和setMapOutputValueClass设置的是map的输出类型,而setOutputKeyClass和setOutputValueClass设置的就只是reduce的输出类型。

上述设置完成后,还需要注意一个地方,那就是setCombinerClass方法必须要注释掉,否则仍然会报错,原因是一般情况下会把reduce方法设置成combiner的类,而数据流是

Mapper<K1, V1, K2, V2> --> Combiner<K2, V2, K3, V3> -->Reducer<K3, V3, K4, V4>

K3,V3和K4,V4类型不同,所以仍会报错,因此需要将

//job.setCombinerClass(Reduce.class);

注释掉即可。

总结一下上述内容:
1)当K2, V2 和K3 , V3类型一致时,只需要使用setOutputKeyClass和setOutputValueClass来设置输出类型即可,setCombinerClass语句无需注释

2)当K2, V2 和K3 , V3类型不一致时,必须使用setMapOutputKeyClass和setMapOutputValueClass来设置map的输出类型,用setOutputKeyClass和setOutputValueClass来设置reduce的输出类型,同时,需要将setCombinerClass语句注释

本人新手,如有不对之处,还请指出,谢谢啦

原创粉丝点击