浅解MapReduce与简单MapReduce程序出包---Hadoop学习笔记(2)

浅略理解MapReduce的概念机制是开始真正使用Hadoop开发Mapreduce程序的第一步,是一个充分条件。理解和实践并进才能让更多的问题暴露对理论的理解的不够。继续学习《Hadoop基础教程》。
1.Map与Reduce
Hadoop将数据分成不小于64MB的块,因此每个数据块都有一个对应的键,而数据块就作为值,由此形成键值对,就是所说的Map,映射。Reduce将Map输出的键值对进行汇集和缩减。有一个清晰的描述:
{K1,V1}>{K2,List<V2>}>{K3,V3}
第一个键值对是Map的输入,Map的输出是第二个键值对所表示的有一个键及对应的值列表组成,其形成的过程是一个叫shuffle的方法。第三个键值对由Reduce缩减输出,也是MapReduce的最终输出。
2.MapReduce的Java API
实践出真知,先贴上总结的示例,再逐步分析。

import org.apache.hadoop.conf.*;
import org.apache.commons.io.IOExceptionWithCause;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.*;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;
import java.io.IOException;
import java.io.InterruptedIOException;

public class WordCount {
    public static class WordCountMapper extends Mapper<Object,Text,Text,IntWritable> {
        private final static IntWritable one =new IntWritable(1);
        private Text word=new Text();
        public void map(Object key,Text value,Context context) {
            String words[]=value.toString().split("\\W");
            try {
                for (String str : words) {
                    word.set(str);
                    context.write(word, one);
                }
            }catch (IOException e) {
                e.printStackTrace();
            }catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
    public static class WordCountReducer extends Reducer<Text,IntWritable,Text,IntWritable> {
        public void reduce(Text key, Iterable<IntWritable> values, Context context) {
            int total = 0;
            for (IntWritable val : values) {
                total+=val.get();
            }
            try {
                context.write(key, new IntWritable(total));
            } catch (IOException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public static void main(String...args)throws Exception {
        Configuration conf=new Configuration();
        Job job=new Job(conf,"word count");
        job.setJarByClass(WordCount.class);
        job.setMapperClass(WordCountMapper.class);
        job.setReducerClass(WordCountReducer.class);
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);
        job.setCombinerClass(WordCountReducer.class);
        FileInputFormat.addInputPath(job,new Path(args[0]));
        FileOutputFormat.setOutputPath(job,new Path(args[1]));
        System.exit(job.waitForCompletion(true)?0:1);
    }
   }

首先说明一下用的IDE是IntelliJ,要在intelliJ上写MapReduce要添加Hadoop的依赖。以防以后忘记,步骤如下:
1.在project Struct下的Modules中添加MapReduce所需要的jar包
2.用的包有

  $ hadoop-2.6.0/share/hadoop/mapreduce
  $ hadoop-2.6.0/share/hadoop/common
  $ hadoop-2.6.0/share/hadoop/common/lib

这三个目录下的jar包。
3.制作好modules后再进入artifacts将Modeles打包成jar包即可
这样我们就完成了MapReduce程序开发的前期准备,我们所梦寐以求的API就都有啦,终于可以写MapReduce程序啦!(好吃力的样子)。
我们自定义的Mapper类和Reducer类都要继承Hadoop的Mapper和Reducer类,分别需要重载实现

void map(K1 key,V1 value,Mapper.Context context) //Context提供与Hadoop框架通信的基本机制
    throws IOException,InterruptedException
{
//TODO
}

void reduce(K1 key,Iterable<V2> values,Reducer.Context context) 
    throws IOException,InterruptedException
{
//TODO
}

map:
在WordCount(字数统计),TextInputFormat提供了以行号为键的映射,map由此形成键值对。
context.write(word, one);语句负责将map方法中的键值对进行输出。
reduce:
负责对map形成的键和一组值的组合进行字数统计。
Map的输入:{IntWritable,Text}
输出:{Text,IntWritable}
Reduce的输入:{Text,IntWritable}
输出:{Text,IntWritable}
main函数是程序的驱动,其参数指明程序的输入和输出的文件位置,即一个Input文件和一个OutPut文件,这两个参数由运行MapReduce时传入。
3.运行MapReduce程序
首先,确保Hadoop已经开启
检查Java虚拟机状态:

4048 Main
5316 DataNode
5800 NameNode
6142 Jps
5487 SecondaryNameNode

首先看一下IntelliJ生成Jar包的位置,然后我们先键入命令:

bin/hadoop jar ~/IdeaProjects/WordCount-Hadoop/out/artifacts/WordCount_Hadoop_jar/WordCount-Hadoop.jar WordCount test.text output

当当,很荣幸地出错了,所以盲目地键入代码而不搞清楚含义很蛋疼啊。我们一步步分析一下以上的命令吧。
bin/hadoop jar “jar”这个是hadoop的命令行中的执行jar命令,我们要进入bin/hadoop才可以执行hadoop的命令,这里我没有深入去了解,以后好惭愧。
jar后面的是我们的jar包的目录,那么我们想,既然有了命令,有了包,为啥后面还跟着三串似曾相识又说不出所以然来的命令呢?
那么我们再发散一下思维,突然想到前面写程序的时候好像也提到参数?往前一看,发现main作为一个驱动,必须传入输入文件位置和输出文件位置。那么这个推理加上猜测,(再加上一次次一堆堆报错),我可以顺理成章地知道,后面三个参数:第一个是WordCount的入口类,第二个是Input文件,第三个是Output文件。那么问题来了,Iuput的位置怎么搞?在那个目录下?随便什么都行吗?
于是我随便创了个input文件放在用户目录下,得到数次报错如下:

Exception in thread "main" org.apache.hadoop.mapreduce.lib.input.InvalidInputException: Input path does not exist: hdfs://localhost:9000/user/coder-z/test.text
    at org.apache.hadoop.mapreduce.lib.input.FileInputFormat.singleThreadedListStatus(FileInputFormat.java:321

吸取实践教训,我发现其实这个input文件需要先上传到hadoop的hdfs文件系统中,而我刚开始配置的时候貌似没有建立相应的hdfs本地文件系统。所以,干脆,直接上传文件到hadoop文件系统中试试,

bin/hadoop fs -copyFromLocal ~/test.text hdfs://localhost:9000/

使用hadoop文件系统中的copyFromLocal命令,将我的input文件传到hdfs中。(这里我也没有去深入了解Hadoop的文件系统,不好意思)
接下来,
键入我们一开始令我懵懵懂懂的命令

bin/hadoop jar ~/IdeaProjects/WordCount-Hadoop/out/artifacts/WordCount_Hadoop_jar/WordCount-Hadoop.jar WordCount hdfs://localhost:9000/test.text output

相应地,对input文件位置做了修改。
值得注意的是,前面的报错说是在hdfs的用户目录下未找到文件,也就是hdfs默认在这个目录中寻找input文件,而我在上传到该用户目录下时却被告知未找到该目录?这个目录是要自己创建的吗?下一次试试看。所以干脆指定input目录在hdfs://localhost:9000下。由于我配置的时候是9000端口,所以是localhost:9000。
好了,键入命令,大功告成(?)。出来的结果令人兴奋,但是,我要的结果呢?
上面提到,我们的最后一个参数是输出位置,那么我们查看一下hadoop文件系统中我们定义为output的

bin/hadoop fs -ls output

首先确认output文件里的内容,应该有两个,一个是_SUCCESS,另一个就是结果output/part-r-00000,后面的00000是reducer输出写入的序号。
查看结果:

bin/hadoop fs -cat output/output/part-r-00000

呼,大功告成(?)


下面一次笔记准备写MapReduce的执行过程(浅略)和初步的MapReudce程序的开发,发现如果要深入理解MapReduce,看教程肯定不够啊,找个时间泛读一下google Mapreduce。
然后是算法算法算法和写代码写代码写代码功底啊,要加油!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值