整套大数据学习资料(视频+笔记)百度网盘无门槛下载:http://www.edu360.cn/news/content?id=3377

7.1. MapReduce 的类型

hadoop 花牛 9℃ 0评论

Hadoop的MapReduce中,mapreduce函数遵循如下常规格式:

map: (K1, V1list(K2, V2)

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

一般来说,map函数输入的键/值类型(K1和V1)不同于输出类型(K2V2)。 虽然reduee函数的输入类型必须与map函数的输出类型相同,但reduce函数的输出类型(K3V3)可以不同于输入类型。例如以下Java接口代码:

public class Mapper<KEYIN, VALUEIN, KEYOUT, VALUEOUT> {
    public class Context extends MapContext<KEYIN> VALUEIN, KEYOUT, VALUEOUT> {
        // ...
    }
    protected void map(KEYIN key, VALUEIN value, Context context) throws IOException, InterruptedException {
        // ...
    }
}
public class Reducer<KEYINJ VALUEIN, KEYOUT, VALUEOUT> {
    public class Context extends ReducerContext<KEYIN, VALUEIN, KEYOUT, VALUEOUT> {
        // ...
    }
    protected void reduce(KEYIN key, Iterable<VALUEIN> values,
        Context context) throws IOException,InterruptedException {
        // ...
    }
}

Context类对象用于输出键/值对,因此它们通过输出类型参数化,这样 write()方法的说明如下:

Public void write(KEYOUT key, VALUEOUT value)
throws IOException, InterruptedException

由于Mapper和Reducer是单独的类,因此类型参数可能会不同,所以MapperKEYIN的实际类型参数可能与Reducer中同名的KEYIN类型参数不一致。例如,在前面章节的求最高温度例子中,MapperKEYIN为 LongWritable 类型,而 Reducer 中为 Text 类型。

类似的,即使map输出类型与reduce的输入类型必须匹配,但这在Java编 译器中并不是强制要求的。

类型参数(type parameter)命名可以不同于抽象类型的定义(KEYIN对应于K1),但它们的格式是相同的。

如果使用combine函数,它与reduce函数的形式相同(它是Reducer的一个实现),不同之处是它的输出类型是中间的键/值对类型(K2V2),这些中 间值可以输入reduce函数:

map: (K1, V1list(K2, V2)

combine: (K2, list(V2)) list(K2, V2)

reduce: (K2, list(V2)) — list(K3, V3)

combine函数与reduce函数通常是一样的,在这种情况下,K3K2类型相同,V3V2类型相同。

partition函数对中间结果的键/值对(K2V2)进行处理,并且返回一个分区索引(partition index)。实际上,分区由键单独决定(值被忽略)

partition: (K2, V2)  integer

或用Java的方式:

public abstrack class Partitioner<KEY,VALUE> {
   public abstract int gerPartition(KEY key, VALUE value, int numPartitions);
}

在老版本的API中,MapReduce的用法非常类似,类型参数的实际命名 也为K1、V1等。在新旧版本API中类型上的约束也是完全一样的。

public abstrack class Partitioner<KEY,VALUE> {
    public abstract int gerPartition(KEY key, VALUE value, int numPartitions);
}
public interface Mapper<Kl, V1, K2, V2> extends JobConfigurable, Closeable {
    void map(K1 key, V1 value, 0utputCollector<K2, V2> output. Reporter reporter) throws IOException;
}
public interface Reducer<K2, V2, K3, V3> extends 3obConfigurable, Closeable {
    void reduce(K2 key, Iterator<V2> values,0utputCollector<K3, V3> output, Reporter reporter) throws IOException;
}
public interface Partitioner<K2, V2> extends 3obConfigurable {
    int getPartition(K2 key, V2 value, int numPartitions);
}

这些理论对配置MapReduce作业有帮助吗?表7-1总结了新版本API的配置选项(表7-2为旧版本API的),把属性分为可以设置类型的属性和必须与类型相容的属性。

输入数据的类型由输入格式进行设置。例如,对应于TextlnputFormat的键类型是LongWritable,值类型是Text。其他的类型通过调用Job类的方法来进行显式设置(旧版本API中使用JobConf类的方法)。如果没有显式设置,中间的类型默认为(最终的)输出类型,也就是默认值LongWritableText。因此,如果K2K3是相同类型,就不需要调用setMapOutputKeyClass(),因为它将调用setOutputKeyClass()来设置同样,如果V2与V3相同,只需要使用setOutputValueClass()

这些为中间和最终输出类型进行设置的方法似乎有些奇怪。为什么不能结合mapper和reducer导出类型?原来,Java的泛型机制有很多限制:类型擦除(type erasure)导致运行过程中类型信息并非一直可见,所以Hadoop不得不进行明确设定。这也意味着可能会在MapReduce配置的作用中遇到不兼容的类型,因为这些配置在编译时无法检查。与MapReduce类型兼容的设置列在表7-1中。类型冲突是在作业执行过程中被检测出来的,所以 一个比较明智的做法是先用少量的数据跑一次测试任务,发现并修正任何类型不兼容的问题。

表7-1 新的MapReduce API中的设置类型

属性

属性设置方法

输入类型

中间类型

输出类型

可以设置类型的属性

K1

V1

K2

V2

K3

V3

mapreduce.job.inputformat.class

setInputFormatClass()

*

mapreduce.map.output.key.class

setMapOutputKeyClass()

*

mapreduce.map.output.value.class

setMapOutputValueClass()

*

mapreduce.job.output.key.class

setOutputKeyClass()

*

mapreduce.job.output.value.class

setOutputValueClass()

*

类型必须一致的属性

mapreduce.job.map.class

setMapperClass()

*

*

*

*

mapreduce.job.combine.class

setCombinerClass()

*

*

mapreduce.job.partitioner.class

setPartitionerClass()

*

*

mapreduce.job.output.key.comparator.class

setGroupingComparatorClass()

*

mapreduce.job.output.group.comparator.class

setGroupingComparatorClass()

*

mapreduce.job.reduce.class

setReducerClass()

*

*

*

*

mapreduce.job.outputformat.class

setOutputFormatClass()

*

*

表7-2旧版本MapReduce API的设置类型

属性

属性设置方法

输入类型

中间类型

输出类型

可以设置类型的属性

K1

V1

K2

V2

K3

V3

mapreduce.input.format.class

setInputFormat()

*

mapreduce.mapoutput.key.class

setMapOutputKeyClass()

*

mapreduce.mapoutput.value.class

setMapOutputValueClass()

*

mapreduce.output.key.class

setOutputKeyClass()

*

mapreduce.output.value.class

setOutputValueClass()

*

类型必须一致的属性

mapred.mapper.class

setMapperClass()

*

*

*

*

mapred.map.runner.class

setMapRunnerClass()

*

*

*

*

mapred.combine.class

setCombinerClass()

*

*

mapred.partitioner.class

setPartitionerClass()

*

*

mapred.output.key.comparator.class

setOutputKeyComparatorClass()

*

mapreduce.output.value.groupfn.class

setOutputValueGroupingComparatorClass()

*

mapreduce.reduce.class

setReducerClass()

*

*

*

*

mapreduce.output.format.class

setOutputFormat()

*

*

转载请注明:全栈大数据 » 7.1. MapReduce 的类型

喜欢 (0)or分享 (0)
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址