WordCount是写hadoop mapreduce入门级程序,会写wordcount的话,基本上80%的mapreduce就懂了。java
mapreduce分为map过程和reduce过程,用户能够根据本身的业务自定义map过程和reduce过程。apache
以wordcount为例,要计算文本中单词出现的个数,须要读取文本,并针对单词进行统计。服务器
package com.hadoop.mapreduce; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.LongWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.Mapper; import java.io.IOException; /** * * Created by Frankie on 2018/1/14. * KEYIN: 默认状况下,是mr框架所读到的一行文本的起始偏移量, Long 在hadoop中有本身的精简序列化接口,因此不直接使用long, 而用LongWritable * VALUEIN: 默认状况下,是mr框架所读到的一行文本的内容, String * KEYOUT: 是用户自定义逻辑处理完成后输出数据中的key, 在此处是单词,String * VALUEOUT: 是用户自定义逻辑处理完成后输出数据中的vlaue, 在次数是单词次数,Integer * * **/ public class WordCountMapper extends Mapper<LongWritable, Text, Text, IntWritable> { /* * map 阶段的业务逻辑就写在自定义的Map()方法中 * map task会对每一行输入数据调用一次咱们自定义map()方法 * */ @Override protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException{ String line = value.toString(); String[] words = line.split(" "); for(String word: words){ // 将单词做为key, 将次数1做为value,以便于后续的数据分发,能够根据单词分发,以便于相同单词会用到相同的reduce task // map task会收集,写在一个文件上 context.write(new Text(word), new IntWritable(1)); } } }
package com.hadoop.mapreduce; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.Reducer; import java.io.IOException; import java.util.Iterator; /** * Created by Frankie on 2018/1/14. * * KEYIN, VALUEIN 对应 mapper输出的KEYOUT, VALUEOUT类型对应 * KEYOUT, VALUEOUT是自定义reduce逻辑处理结果的输出数据类型 * KEYOUT是单词, * VALUE是总次数 */ public class WordCountReducer extends Reducer<Text, IntWritable, Text, IntWritable> { @Override protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException{ /* 入参key, 是一组相同单词kv对的key Context 上下文 * */ int count = 0; // Iterator<IntWritable> iterator = values.iterator(); // while(iterator.hasNext()){ // count += iterator.next().get(); // } // for( IntWritable value: values){ count += value.get(); } context.write(key, new IntWritable(count)); } }
mapreduce过程存在一些问题,好比,app
Map task如何进行任务分配?框架
Reduce task如何进行任务分配?ide
Map task与 reduce task如何进行衔接?oop
若是某map task 运行失败,如何处理?code
Map task若是都要本身负责数据的分区,很麻烦orm
为例解决这些问题,须要有个master专门对map reduce进行管理。接口
在WordCount文件中,有专门对做业进行配置,以及最后将代码提交到客户端。
package com.hadoop.mapreduce; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.Job; import org.apache.hadoop.mapreduce.lib.input.FileInputFormat; import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; /** * Created by Frankie on 2018/1/14. * * 至关于yarn集群的客户端 * 须要在此封装mr程序的相关运行参数,指定jar包,最后提交给yarn */ public class WordCount { public static void main(String[] args) throws Exception{ Configuration conf = new Configuration(); Job job = Job.getInstance(conf, "wordcount"); // 指定本程序的jar包所在的本地路径 job.setJarByClass(WordCount.class); // 指定本业务使用的map业务类 job.setMapperClass(WordCountMapper.class); job.setReducerClass(WordCountReducer.class); // 指定mapper输出数据的kv类型 job.setMapOutputKeyClass(Text.class); job.setMapOutputValueClass(IntWritable.class); //指定最终输出的数据的kv类型 job.setOutputKeyClass(Text.class); job.setOutputValueClass(IntWritable.class); //指定job的输入原始文件所在目录 // /data/adult.data FileInputFormat.setInputPaths(job, new Path(args[1])); // 指定job的输出结果所在目录 FileOutputFormat.setOutputPath(job, new Path(args[2])); // // 将job中配置的相关参数,以及job所用的java类所在的Jar包,提交给yarn去运行 // job.submit(); // 提交job配置,一直等待到运行结束 boolean res = job.waitForCompletion(true); System.exit(res? 0: 1); } }
代码编辑完成后,对代码进行打包。咱们在这里选择不依赖第三方包的打包方式进行打包。
打完包后,将生成的jar包提交到服务器中去。 并执行,
leiline@master:~/Documents/hadoop/myJars$ hadoop jar HadoopMapReduce.jar com.hadoop.mapreduce.WordCount /data/adult /data/out
注意,out文件是由程序自动建立的,不须要用户手动去建立。最后,代码执行完毕后,能够在hdfs中看到执行的结果:
Found 2 items -rw-r--r-- 3 leiline supergroup 0 2018-01-14 19:01 /data/out/_SUCCESS -rw-r--r-- 3 leiline supergroup 216737 2018-01-14 19:01 /data/out/part-r-00000