用一个10行代码的案例,一个没有map和reduce的类分解Mapreduce过程。
操作过程:
1>:创建MapReduce项目,并配置Run Configuration选项中的Argument输入输出路径.如图
2>:再看代码
public class MyWordCount{
/**
* @param args
* @throws IOException
* @throws ClassNotFoundException
* @throws InterruptedException
*/
public static void main(String[] args) throws IOException, InterruptedException, ClassNotFoundException {
//根据安装的Hadoop夹下conf文件创建对象
Configuration conf = new Configuration();
//根据Run Configuration设置下的arguments 下的选项得到输入输出路径
String [] otherArgs=new GenericOptionsParser(conf, args).getRemainingArgs();
if(otherArgs.length!=2){
System.err.println("Usage:wordcount <in> <out>");
System.exit(2);
}
//定义一个job
Job job=new Job(conf, "My WordCount");
//制定输入输出路径
FileInputFormat.addInputPath(job,new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));
//等待job执行完毕退出
System.exit(job.waitForCompletion(true)?0:1);
}
}
3>执行结果
文件源如图:
执行结果如图:
结果分析:
1>事实
源文件有两个,用户没有自己定义任何Map和Reduce的情况下,执行后依旧可以得到MapReduce结果,当然前提是使用了插件创建的是MapReduce项目.并非是一个单纯的Java 项目.
2>过程解析
第一步:首先使文件会被分为特定大小的split,叫做分区每一个split会对应启动一个task.分别执行的是MapTask和ReduceTask.
第二步:每一个split首先会被hadoop框架分解成一个个的<key,Value>对,具体是<偏移量,文本行>(偏移量指的是每个文本行的首字母对文件的初始位置的偏移,文本行是以/r/n来判断的). 如此形式:
<0,zhong nan da xue>
<14,hu nan da xue>
<27,shi fan da xue>
第三步:交由用户自定义的Map处理.以系统的wordcount为例,执行程序中的命令得到的结果是: <zhong,1>,<nan,1><da,1>,<xue,1>,<hu,1>,<nan,1>.....
第四步:sort过程.即排序.
<zhong,list(1)>
<nan,list(1,1)>
<da,list(1,1,1)>....
显然是将文件中有相同的key的进行排序,以这种格式发送给Reduce,有助于解决带宽问题.
第五步:shuffle过程,翻译为洗牌过程.顾名思义,洗牌是将牌打乱再分配的过程.对应的是reduce任务取得map任务输出的文件.这个过程是hadoop框架自动实现的,默认是按照hash函数执行的(此处不做深入分析).此过程后就将文件传给了reduce了.
第六步:执行reduce.还是以wordcount为例.j将list中的数字相加得到:
<zhong,1>
<nan,2>
<da,3>....
分析本案例:
本案例中没有定义任何map和reduce,得到了上述的结果是因为没有执行用户自定义的map和reduce,所以是以第二步之后的结果形式展现的,这是默认的形式.
以上只是很概括的展现了map和reduce的过程,还有很多细节值得深入,未完待续.....