Hadoop提供了最简单的Map/Reduce编程实例WordCount,本文对该Demo的程序结构,以及Map/Reduce框架的注意事项,进行了分析。
值得注意的一点是,Hadoop仍在不断的衍化中,本文的例子针对的是版本0.18.3。Release不久的0.20.0对Mapper/Reducer接口已经有所变化,不过影响不大。
Class Name: WordCount
extends Configured implements Tool
实现Tool接口的目的,是为了支持org.apache.hadoop.util.GenericOptionsParser的使用
实现run(): 通过ToolRunner.run()可以Invoke这个方法。
接口定义:public int run(String[] args) throws Exception {}
流程:
1. load配置:JobConf conf = new JobConf(getConf(), WordCount.class);
配置是通过-conf参数传入,没有的话,采用默认配置。
JobConf extends Configuration
2.设置JobConf的一些成员
conf.setJobName("wordcount");
conf.setMapperClass(MapClass.class);
conf.setCombinerClass(Reduce.class);
conf.setReducerClass(Reduce.class);
conf.setNumMapTasks(); // 实际的Map Task数目由Job Tracker根据Cluster情况确定,不一定跟设置相同
conf.setNumReduceTasks();
conf.setInputFormat(TextInputFormat.class);
conf.setOutputFormat(TextOutputFormat.class);
conf.setOutputKeyClass(Text.class);
conf.setOutputValueClass(IntWritable.class);
3. 设置输入、输出的Path
FileInputFormat.setInputPaths(conf, "HDFS PATH");
FileOutputFormat.setOutputPath(conf, "HDFS PATH");
4. 提交Job
JobClient.runJob(conf);
JobClient是用户Job跟JobTracker交互的接口,可以用来提交Job、跟踪Job进度、访问Task日志、获取Map-Reduce cluster状态信息。
Job提交会进行如下操作:
1) 检查Job的输入、输出specifications。
2) 计算Job的InputSplits
3) 必要的话,计算Job的DistributedCache的Account信息。
4) 拷贝jar和配置文件到HDFS上。
5) 提交Job到JobTracker,并监控其状态。
提交Job的方式:
为了便于Job Control,如采用系列的Map/Reduce完成一项复杂任务,需要根据Job的完成情况做出判断,有几种方式:
RunningJob JobClient.runJob() job完成后才返回
RunningJob JobClient.submitJob() 只提交job,然后poll RunningJob的return handle
JobConf.setJobEndNotificationURI(String) 设置job-completion的notification,避免poll。
Hadoop API说明:建议用Configuration代替JobConf(Deprecated)。
Map-Reduce框架自动做了下面的工作:
1. Map-Reduce FrameWork为每个InputSplit spawn一个map任务。
InputSplit由InputFormat生成。
Mapper实现可以通过JobContext.getConfiguration()访问Job configuration。
2. Framework调用setup(org.apache.hadoop.mapreduce.Mapper.Context)
3. 然后,为InputSplit中每个key/value pair调用map(Object, Object, Context)
4. 最后,调用cleanup(Context)
intermedidate values根据output key分组,即Partition。
分组后的values传递到Reducer
在传递到Reducer之前,可以自定义Combiner
Mapper和Reducer的实现方式如下。
实现Mapper:
接口:public static class MapClass extends MapReduceBase
implements Mapper<LongWritable, Text, Text, IntWritable> {}
MapReduceBase is Deprecated
实现map():
注意:map()接口在hadoop-0.20.0版中发生变化,原来接口中的OutputCollector<K2, V2>和Reporter被封装为Mapper.Context。
实现Reducer:
接口: public static class Reduce extends MapReduceBase
implements Reducer<Text, IntWritable, Text, IntWritable> {}
main函数:
调用ToolRunner.run()
eg: ToolRunner.run(new Configuration(), new WordCount(), args);