Hadoop实践(三)---MR作业运行(源码详解)
来源:互联网 发布:中国广电网络全国整合 编辑:程序博客网 时间:2024/06/06 13:02
要运行MapReduce作业首先要编写MR程序。
MR程序主要包括三个部分:Map类,Reduce类和驱动类。
定义一个反向索引的例子,首先需要定义map类,reduce类需要将输入数据中的每个单词单独显示一行,那么map 的输出key应该是输入文件中的每个单词,然后MR将这些key合并到一起,每个key 的值将包含文件名
map类代码:
public static class Map extends Mapper<LongWritable, Text, Text, Text> { //在扩展MR的mapper类时,需要确定输入和和输出的键值的数据类型。在作业中使用MR默认的InputFormat,该类将输入文件中的字节偏移量作为键,将每一行的数据作为值 private Text documentId; //输入以文本对象的形式存储文件名 private Text word = new Text(); //为了减少对象的创建,需要创建一个可以复用的单一的文本对象 @override protected void setup(Context context){ //上下文中提取文件名 //setup方法在map方法调用之前执行,使用这个机会存储map中的输入文件名 String filename = ((FileSplit)context.getInputSplit()).getPath().getName(); documentId = new Text(filename); } public void map(LongWritable key, Text value, Context context ) throws IOException, InterruptedException {//每行输入都要调用map方法,map任务同步处理输入文件的子集 for(String token: StringUtils.split(Value.toString())){ //value包括文件的一整行,使用StringUtils(比String.split效率高)标记每行的值 word.set(token); context.write(word,documentId); //map输出中word作为键,文件名最为值 } } }
reduce类代码
reduce方法的主要作用是为每个单词创建单独的输出行,并列出包含该单词的文件名。一旦每个逐渐及其文件名被map方法列出,MR框架将会调用reducer,reduce方法需要执行的就是将文件ID合并到一起,并输出合并结果
public static class Reduce extends Reducer<Text, Text, Text, Text> {//在定义reducer时需要指定输入和输出键值类型 private Text docIds = new Text(); public void reduce(Text key, Iterable<Text> values,Context context) throws IOException, InterruptedException {//每个独立的map输出键都要调用reduce方法,Iterable允许对同一个键对应的所有值进行迭代操作 HashSet<Text> uniqueDocIds = new HashSet<Text>();//将同一个键对应的文件名保存在一个Set中 for (Text docId : values) {//对同一个键对应的索引文件名进行迭代 uniqueDocIds.add(new Text(docId))//将文件名加入Set中,创建新Text对象的目的是MR在迭代values的时候,可以复用这个Text对象,即可以创建新的副本 } docIds.set(new Text(StringUtils.join(uniqueDocIds,","))); context.write(key, docIds);//reduce输出一个词,已经包含这个词的文件名列表,这个列表是以CSV格式进行分割的 } }
驱动类代码
驱动类代码可以设置启动MR作业的所以需要的属性。需要在MR框架上定义map和reduce函数可以使用哪些类,并定义输出与输入结果的存储位置。
默认情况下,MR可以处理文本文件,如果需要处理复杂的文件结构,需要使用不同的数据存储技术,那么就需要定义MR框架如何读取这样的数据源。
public static void main(String[] args) throws Exception { Configuration conf = new Configuration();//为作业做的配置容器,map和reduce类可以从这里获取设置的任何值 String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();//输入是一个或多个文件,需要创建一个输入参数的子数组,包括数组的最后一个项目,即MR作业的输出目录 if (otherArgs.length < 2) { System.err.println("Usage: wordcount <in> [<in>...] <out>"); System.exit(2); } Job job = Job.getInstance(conf, "word count"); job.setJarByClass(WordCount.class);//任务类的setJarByClass方法定义哪些Jar包需要通过Hadoop来同步复制到集群中,并在随后的任务中同时设置classpath引用传入的类,使得,MapReduce类可以被任务所调用 job.setMapperClass(Map.class);//为作业设置map类 job.setCombinerClass(Reduce.class);//为作业设置combine类 job.setReducerClass(Reduce.class);//为作业设置reduce类 job.setOutputKeyClass(Text.class);//如果map输出的键和值与输出类型不同时,需要告诉Hadoop它们输出的时候是什么类型 job.setOutputValueClass(Text.class);//设置map输出值的类 for (int i = 0; i < otherArgs.length - 1; ++i) { FileInputFormat.addInputPath(job, new Path(otherArgs[i]));//设置作业HDFS的输入文件,Hadoop可设置多个输入文件,文件名使用逗号隔开 } //另一种设置输入路径的方式 //FileInputFormat.setInputPath(job,StringUtils.join(otherArgs,",")); FileOutputFormat.setOutputPath(job, new Path(otherArgs[otherArgs.length - 1]));//设置作业HDFS的输出目录 Path output = new Path(otherArgs[otherArgs.length - 1]) ; output.getFileSystem(conf).delete(output.true);//如果在HDFS上存在这个目录,就把它删除,否则该目录的存在会导致作业失败 System.exit(job.waitForCompletion(true) ? 0 : 1);//通知集群运行这个作业,并阻塞直到作业完成 }
阅读全文
0 0
- Hadoop实践(三)---MR作业运行(源码详解)
- Hadoop实践(四)---MR作业配置
- MR源码学习(三)
- Hadoop实践(四)---Hadoop集群测试(MR样例)
- Hadoop教程(三): MR重要运行参数
- Hadoop实践(四)---MR Job卡住的问题
- Hadoop实践(五)---MR相对SQL的应用
- Spark源码系列(三)作业运行过程
- Spark源码系列(三)作业运行过程
- Spark源码系列(三)作业运行过程
- hadoop实践(三)hadoop 集群配置
- Hadoop作业提交分析(三)
- Hadoop作业提交分析(三)
- Hadoop作业提交分析(三)
- Hadoop作业提交分析(三)
- hadoop运行MR程序笔记
- MR源码学习(一)
- MR源码学习(二)
- 如何下载谷歌矢量高程等高线
- Android微信授权app登陆
- iOS
- 嵌入式笔试题(1)
- 4.7复用类
- Hadoop实践(三)---MR作业运行(源码详解)
- angular中的select标签的使用
- Django程序部署-uwsgi
- post表单数组数据验证
- 虚析构函数
- 【PHP学习】一次完整的HTTP请求所经历的7个步骤
- 关于虚拟按键和状态栏控制
- [leetcode]54. Spiral Matrix
- linux挂载大磁盘