第6章Hadoop分布式离线计算框架-MapReduce

       

目录

6.1MapReduce概述

6.1.1MapReduce的特点

6.1.2MapRedcue的应用场景

6.2MapReduce执行过程

6.2.1单词统计实例

6.2.2MapReduce执行过程

6.2.3Map Reduce的文件切片---Split

6.2.4Map过程和Reduce过程

6.2.5Shuffle过程

6.3MapReduce实例

        (1)本机配置Hadoop环境变量

        (2)放置winutil.exe文件和hadoop.dll

        (3)新建一个Java工程,导入需要的JAR包。新建一个WordCountMapper类

         (4)新建一个WordCountReducer类

        (5)创建主方法:

         (6)创建处理文件

        (7)运行结果

         常见问题汇总:


        Hadoop中有两个重要的组件,一个是HDFS,另一个是MapReduce,HDFS用来存储大批量得数据,而MapReduce则是通过计算来发现数据中有价值得内容。

6.1MapReduce概述

        hadoop作为开源组织下最重要得项目之一,最推出后得到了全球学术界和工业界的广泛关注、推广和普及。它是开源项目Lucene(搜索索引程序库)和Nutch(搜索引擎)的创始人Doug Cutting于2004年推出的,当时Doug Cutting 发现MapReduce正是其所需要解决大规模Web数据处理的重要计数,而因模仿Goole MapReduce,基于Java设计开发了一个成为hadoop的开源MapReduce并行计算框架和系统。

6.1.1MapReduce的特点

        我们前面说过hadoop的HDFS用于存储数据,MapReduce用来计算数据。接着来介绍一下MapReduce的特点。MapReduce适合处理离线的海量数据,这里的“离线”可以理解为本地存储,非实时处理。李先计算旺旺需要一段时间,如几分钟或者几个小时们根据业务数据和业务复杂程度有所区别。MapReduce往往处理大批数据,比如PB级或者AB级别。特点如下

        易于编程:如果要编写分布式程序,只需要实现一些简单的接口,与编写普通程序类似,避免了复杂的过程。同时,编写的这个分布式程序可以部署到大批廉价的普通机器上运行。

        具有良好的拓展性:是指当一台机器的计算资源不能满足存储或者计算的时候,可以通过增加机器来增加存储和计算能力。

        具有高容错性:MapReduce设计的初衷是可以使程序部署运行在链家的机器上,廉价的机器坏的概率相对较高,这就要求其具有良好的容错性。当一台机器“挂掉”以后,相应数据的存储和计算能力会被一直到另外一台机器上,从而实现容错性。

6.1.2MapRedcue的应用场景

        MapReduce的应用场景主要变现在从大规模数据中进行计算,不要求即时返回结果的场景,比如以下典型应用

        单词统计

        简单的数据统计,如网站PV和UV统计

        搜索引擎建立索引

        搜索引擎中,统计最流行的K个搜索词

        统计搜索词频率,帮助优化搜索词提示

        复杂数据分析算法实现

        下面介绍MapReduce不适用的方面:

        实时计算,MapReduce不适合在毫秒级或者秒级内返回结果。

        流式计算,MapReduce的输入数据是静态的,不能动态变化,所以不适合流式计算。

        DAG计算,如果多个应用程序存在一栏关系,并且后一个应用程序的输入为前一个的输出,这种情况也不适合。

6.2MapReduce执行过程

6.2.1单词统计实例

        假设有一个非常大的文件,需求是统计文件中每个单词的出现的次数,MapReduce的执行过程如下图

第6章Hadoop分布式离线计算框架-MapReduce_第1张图片

        图中主要分为Split、Map、Shuffle、和Reduce阶段,每个阶段在WordCount中的作用如下:

        Split阶段:首先大文件被切成多分,假设这里被切成了3份,每一行代表一份

        Map阶段:解析出每个单词,并在后面机上数字1

        Shuffle阶段:将每一份中的单词分组到一起,并按照字母进行排序

        Reduce阶段,将相同的单词进行累加

        输出结果

6.2.2MapReduce执行过程

        从WrodCount实例中,可以给予单词统计大概了解列MapReduce过程。接下来我们从理论层面面介绍一下

第6章Hadoop分布式离线计算框架-MapReduce_第2张图片

         具体执行过程树下:

        (1)数据会被切割成数据片段

        (2)数据片段以key和value的形式被读进来,默认是以行的下标位作为key,以行的内容作为value

        (3)数据会传入Map中进行处理,处理逻辑由用户自行定义,在Map中处理完后还是以key和value的形式输出。

        (4)输出的数据传给列Shuffle(洗牌),Shuffle完成对数据的排序和合并等操作,但是Shuffle不会对输入的数据进行改动,所以还是key2、value2

        (5)数据随后传给Reduce进行处理,Reduce处理完成后,生成key3、value3

        (6)Reduce处理完成后数据会被写到HDFS某个目录

6.2.3Map Reduce的文件切片---Split

        Split的大小默认与 block对应,也可以由用户任意控制。MapReduce的SPlit大小计算公式如下:

        max(min.split,min(max.split,block))

        其中,max.split = totalSize/numSplit,totalSplit为文件大小,numSplit为用户设定的maptask个数,默认为1:min.split = InputSplit的最小值,具体可以在配置文件中修改参数maperd.mi.split.size,不配置默认为1B,block是HDFS中块的大小。

        举一个例子来说:把一个258MB的文件上传到HDFS上,假设block块大小是128MB,那么它就会被分成3个block块,与之对应产生3个Split,所以最终会产生3个maptask。而第三个block块里存的文件大小只有2MB,他的block块大小是128,那么他实际占用多大空间呢?通过上述公式可知其专用的实际的文件大小,而非一个块的大小。

6.2.4Map过程和Reduce过程

        Map的实现逻辑和Reduce的实现逻辑都是由程序员完成的,其中map的个数和Split的个数对应起来,也就是说一个Split切片对应一个Map任务,关于Reduce的默认数是1,程序员可以自行设置。另外需要注意的是,一个程序可能只有一个map任务缺没有Reduce任务,也可能是多个MapReduce程序串接起来,比如把第一个MapReduce的输出结果作为第二个MapReduce的输如。通过阅读后面的MapReduce实例,我们会对Map和Reduce有进一步的理解。

6.2.5Shuffle过程

        Shuffle又叫洗牌,它起到连接Map任务与Reduce任务的作用列,在这里需要注意的是,Shuffle不是一个单独的任务,他是MapReduce执行中的步骤,如下图。

        从下图可以看出,Shuffle分为两部分,一部分在Map端,一部分在Reduce端,Map处理后的数据会以 key、value的形式存在缓冲区中(buffer in memory),缓冲区大小为128MB。当该缓冲区快要溢出时(80%),会将数据写到磁盘中生成文件,也就是溢写操作(spill to disk)。溢写磁盘的过程是由一个线程来完成,溢写之前包括Partition(分区)和sort(排序),Partition和Sort都有默认实现,其中Partition分区默认是按照“hash”和“%reduce数量”进行分区的,分区之后的数据会进入不同的Reduce,而Sort是默认按照字母顺序进行排序的。我们可以根据也无需求进行编写,具体可以参考后面的实例。溢写之后会在磁盘上生成多个文件,多个文件会通过merge线程完成文件的合并,由多个小文件生成一个大文件。

        合并之后的数据(以key和value的形式存在)会基于Partition被发送到不同的Reduce上,如下图中人去之间的长箭头所示,Reduce会从不同的Map上取得“属于”自己的数据并写入磁盘,完成merge操作减少文件数量,并调用Reduce程序,最终通过Output完成输出。  

第6章Hadoop分布式离线计算框架-MapReduce_第3张图片

6.3MapReduce实例

        前面我们通过一个WordCount实例介绍列MapReduce执行过程,在这里用一个WordCount的单词统计实例来介绍如何编写MapReduce程序。

        一个完整的MapReduce程序主体主要分为两个部分,一个Mapper一个Reduce

        用户自定义Mapper.java类解析key/value对值,然后产生一个中间key/value对值的集合,把虽有具有相同中间key值的中间value值集合在一起后传递给Reduce函数。

        用户自定义的Reduce.java类接受一个中间key的值和相关的一个value值的集合。Reduce函数合并这些value值,形成一个较小的value值的集合。每次Reduce函数调用时只产生0个或1个value输出值。通常我们通过一个迭代器把中间的value值提供给Reduce函数,这样就可以处理无法全部放入内存中的大量value值的集合。

        在编写代码之前,可以先进行本机环境配置,我们也可以将程序打包后上传到centos中执行。

        配置步骤如下:

        (1)本机配置Hadoop环境变量

第6章Hadoop分布式离线计算框架-MapReduce_第4张图片

        (2)放置winutil.exe文件和hadoop.dll

        文件放入hadoop解压目录下的bin文件夹里,如下图

第6章Hadoop分布式离线计算框架-MapReduce_第5张图片

        关于第二部回头我会上传一个资源包给你们。 里面有简单的说明文档。

        (3)新建一个Java工程,导入需要的JAR包新建一个WordCountMapper类

        继承Mapper,这是一个Map过程,对输入文本进行词汇的分割并循环输出给Reducer。代码如下(下面的3个类都是我新建的)。关于导入什么JAR包,我是把hadoop/share/hadoop里面的包基本上都导入进去了。

第6章Hadoop分布式离线计算框架-MapReduce_第6张图片

import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;


public class WordCountMapper extends Mapper{

    @Override
    protected void map(LongWritable key,Text value,Context context)
        throws IOException,InterruptedException{
        //用空格进行分词
        String[] str = value.toString().split(" ");
        //for循环
        for (int i=0;i

         (4)新建一个WordCountReducer类

        继承Reducer;这是一个Reduce过程,将从Map传入的词汇进行分组合并,并通过文本和单词统计量的方式输出。

import java.io.IOException;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.mapreduce.Reducer;

//mapper切分后时 a1 b1 c1 的形式,输出 a2 b1 c1形式
public class WordCountReducer extends Reducer{
    //数据分组合并输出
    @Override
        protected void reduce (Text arg0,Iterable arg1,Context arg2)
            throws IOException,InterruptedException{
            int sum=0;
            for(IntWritable i:arg1){
                sum = sum+i.get();
            }
            arg2.write(arg0,new IntWritable(sum));
        }

}

        (5)创建主方法:

        上面编写了Mapper和Reducer,为了使Mapper和Reducer正常运行,还需要编写主方法。主方法中我们需要先设置连接的HDFS和尧都区的文件及处理后的文件在HDFS中的路径,指明我们所要进行的Map和Reduce过程的类,然后开始MapReduce的离线数据处理

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.yarn.webapp.hamlet.Hamlet;
import org.omg.CORBA.PUBLIC_MEMBER;

import java.io.IOException;

public class Runjob {
    public static void main(String[] args){
        Configuration  conf = new Configuration();
        //namenode入口IP
        conf.set("fs.defaultFS","hdfs://192.168.252.15:9000");   //大家按照自己的主机修改IP
        Job job = null;
            try {
                 //任务名字
                job = Job.getInstance(conf,"mywc");

            }catch (IOException e1){
                e1.printStackTrace();;
            }
            //非主方法
            job.setJarByClass(Runjob.class);
                //map方法
            job.setMapperClass(WordCountMapper.class);
            //reducer方法
            job.setReducerClass(WordCountReducer.class);
            //map输出key类型
            job.setOutputKeyClass(Text.class);
            //map输出value类型
            job.setOutputValueClass(IntWritable.class);
            try{
                //读取位置
                FileInputFormat.addInputPath(job,new Path("/usr/input/data/wc"));
                //处理完成之后的位置
                FileOutputFormat.setOutputPath(job,new Path("/usr/output/data/wc"));
                boolean f = job.waitForCompletion(true);

            }catch (Exception e){
                e.printStackTrace();
            }
    }
}

         (6)创建处理文件

vim test.txt

第6章Hadoop分布式离线计算框架-MapReduce_第7张图片

         在hdfs上创建自己的输入文件夹,就是刚才代码中的路径

hdfs dfs -mkdir -p /usr/input/data/wc  #创建输入目录

hdfs dfs -put test.txt /usr/input/data/wc  #将文件放入目录

         输出文件不需要被创建,代码运行的时候自己会创建

        (7)运行结果

第6章Hadoop分布式离线计算框架-MapReduce_第8张图片

         常见问题汇总:

Error running' xxxxxx': Command line is too long. Shorten command line for xxxxxxxxx_zcc_heu的博客-CSDN博客

class com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$Text - 墨飞_Max - 博客园

        还有大家学习这个的时候,按照我这个步骤来,例如:先配置完环境变量和文件放入之后再打开IEDA。否则你颠倒过来,你得重启IDEA。

        然后顺序对了,代码认真敲那就没问题的。

你可能感兴趣的:(hadoop,big,data,mapreduce)