MapReduce入门1

Posted 小hu_study

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MapReduce入门1相关的知识,希望对你有一定的参考价值。

1.MapReduce介绍

1.1MapReduce简介

Hadoop MapReduce是一个软件框架,用于轻松编写应用程序,这些应用程序以可靠,容错的方式并行处理大型硬件集群(数千个节点)上的大量数据(多TB数据集)。

MapReduce是一种面向海量数据处理的一种指导思想,也是一种用于对大规模数据进行分布式计算的编程模型。

1.2MapReduce特点

(1)易于编程:Mapreduce框架提供了用于二次开发得接口;简单地实现一些接口,就可以完成一个分布式程序。

(2)良好的扩展性:当计算机资源不能得到满足的时候,可以通过增加机器来扩展它的计算能力。

(3)高容错性:Hadoop集群是分布式搭建和部署得,任何单一机器节点宕机了,它可以把上面的计算任务转移到另一个节点上运行,不影响整个作业任务得完成,过程完全是由Hadoop内部完成的。

(4)适合海量数据的离线处理:可以处理GB、TB和PB级别得数据量

1.3MapReduce局限性

(1)实时计算性能差:MapReduce主要应用于离线作业,无法作到秒级或者是亚秒级得数据响应。

(2)不能进行流式计算:流式计算特点是数据是源源不断得计算,并且数据是动态的;而MapReduce作为一个离线计算框架,主要是针对静态数据集得,数据是不能动态变化得。

2.Hadoop MapReduce编程

2.1MapReduce架构体系

(1)MRAppMaster:负责整个程序的过程调度及状态协调。

(2)MapTask:负责map阶段的整个数据处理流程。

(3)ReduceTask:负责reduce阶段的整个数据处理流程。

2.2Map Reduce工作执行流程

执行流程:

map阶段:

负责把从数据源读取来到数据进行处理,默认情况下读取数据返回的是kv键值对类型,经过自定义map方法处理之后,输出的也应该是kv键值对类型。

shuffle阶段:

map输出的数据会经过分区、排序、分组等自带动作进行重组,相当于洗牌的逆过程。这是MapReduce的核心所在,也是难点所在。也是值得我们深入探究的所在。

默认分区规则:key相同的分在同一个分区,同一个分区被同一个reduce处理。

默认排序规则:根据key字典序排序

默认分组规则:key相同的分为一组,一组调用reduce处理一次。

reduce阶段:

负责针对shuffle好的数据进行聚合处理。输出的结果也应该是kv键值对。

2.3​​​​​Hadoop的序列化机制

Hadoop的序列化没有采用java的序列化机制,而是实现了自己的序列化机制。原因在于java的序列化机制比较臃肿,重量级,是不断的创建对象的机制,并且会额外附带很多信息(校验、继承关系系统等)。但在Hadoop的序列化机制中,用户可以复用对象,这样就减少了java对象的分配和回收,提高了应用效率。

2.4了解hadoop中数据类型

Hadoop 数据类型

Java数据类型

备注

BooleanWritable

boolean

标准布尔型数值

ByteWritable

byte

单字节数值

IntWritable

int

整型数

FloatWritable

float

浮点数

LongWritable

long

长整型数

DoubleWritable

double

双字节数值

Text

String

使用UTF8格式存储的文本

MapWritable

map

映射

ArrayWritable

array

数组

NullWritable

null

当<key,value>中的key或value为空时使用

Hadoop提供了以上内容的数据类型,这些数据类型都实现了WritableComparable接口,以便用这些类型定义的数据可以被序列化进行网络传输和文件存储,以及进行大小比较。


3.MapReduce实际操作1

3.1案列引入

WordCount中文叫做单词统计、词频统计,指的是使用程序统计某文本文件中,每个单词出现的总次数。

例如

#输入数据 1.txt

hello hadoop hello hello

hadoop allen hadoop

.....

#输出结果

hello 3

hadoop 3

allen 1

3.2​​​​​​​MapReduce编程思路

 图解如下:

map阶段的核心:把输入的数据经过切割,全部标记1。因此输出就是<单词,1>。

shuffle阶段核心:经过默认的排序分区分组,key相同的单词会作为一组数据构成新的kv对。

reduce阶段核心:处理shuffle完的一组数据,该组数据就是该单词所有的键值对。对所有的1进行累加求和,就是该单词的总次数。最终输出<单词,总次数>。

3.3代码实现功能

(1)编程环境搭建

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>mappreduce_11</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-common</artifactId>
            <version>3.1.4</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-hdfs</artifactId>
            <version>3.1.4</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>3.1.4</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-mapreduce-client-core</artifactId>
            <version>3.1.4</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.29</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>2.4</version>
                <configuration>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <classpathPrefix>lib/</classpathPrefix>
                            <mainClass></mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.0</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

(2)编写Mapper类和​​​Reducer类编写

package word.out_in;


import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;

import java.io.IOException;
/*
    1:继承Mapper类
       四个泛型:K1,V1,K2,V2 类型
 */

public class WordCountMapper extends Mapper<LongWritable, Text,Text,LongWritable> 
    /*
        2:重写map方法,在该方法中将K1、V1转为K2和V2
           key   :就是K1
           value :就是V1
           Context:表示上下文对象
     */
    private Text keyOut = new Text();
    private final static LongWritable valueOut = new LongWritable(1);
    @Override
    protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException 
        //将读取的一行内容根据分隔符进行切割
        String[] words = value.toString().split("\\\\s+");
        //遍历单词数组
        for (String word : words) 
            keyOut.set(word);
            //输出单词,并标记1
            context.write(new Text(word),valueOut);
        
    

package word.out_in;


import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;

import java.io.IOException;

/*
  1:自定义类继承Reducer类
       四个泛型:K2 ,V2,K3,V3 类型
 */
public class WordCountReducer extends Reducer<Text, LongWritable,Text,LongWritable> 
    /*
       2:重写reduce方法,在该方法中将K2,[V2]转为K3和V3
         key:K2
         values: [V2]
     */

    private LongWritable result = new LongWritable();

    @Override
    protected void reduce(Text key, Iterable<LongWritable> values, Context context) throws IOException, InterruptedException 
        //统计变量
        long count = 0;
        //遍历一组数据,取出该组所有的value
        for (LongWritable value : values) 
            //所有的value累加 就是该单词的总次数
            count +=value.get();
        
        result.set(count);
        //输出最终结果<单词,总次数>
        context.write(key,result);
    

(3)编写实现类

public class WordCountDriver1 

    public static void main(String[] args)  throws Exception
        //配置文件对象
        Configuration configuration = new Configuration();

        // 创建作业实例
        Job job = Job.getInstance(configuration, "wordcount");
        // 设置作业驱动类(不加该参数,有的电脑系统会报错)
        job.setJarByClass(WordCountDriver1.class);

        // 设置作业mapper reducer类
        job.setMapperClass(WordCountMapper.class);
        job.setReducerClass(WordCountReducer.class);

        // 设置作业mapper阶段输出key(K2) value(V2)数据类型
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(LongWritable.class);

        //设置作业reducer阶段输出key(K3) value(V3)数据类型 也就是程序最终输出数据类型
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(LongWritable.class);

        // 配置作业的输入数据路径
       FileInputFormat.addInputPath(job,new Path("file:///D:\\\\in-or-out\\\\wordcount"));
//        FileInputFormat.addInputPath(job,new Path("hdfs://node1:8020/input/wordcount"));
       // FileInputFormat.addInputPath(job,new Path(args[0]));
        // 配置作业的输出数据路径,该路径不能存在,否则报错
        Path outputPath = new Path("file:///D:\\\\in-or-out\\\\word");
        FileOutputFormat.setOutputPath(job,outputPath);

        //判断输出路径是否存在 如果存在删除
      FileSystem fileSystem = FileSystem.get(new URI("file:///"),configuration);
        //FileSystem fileSystem = FileSystem.get(new URI("hdfs://node1:8020"),configuration);
        boolean bl = fileSystem.exists(outputPath);
        if(bl)
            fileSystem.delete(outputPath,true);
        
        // 提交作业并等待执行完成
        //job.submit(); //第一代写法,但是不能详尽的输出运行过程
        boolean flag = job.waitForCompletion(true);//第二代,true表示一直监控任务完成,并打印大量的运行过程日志
//程序退出
        //退出任务进程
        System.exit(flag ? 0 : 1);
    

该代码操作需搭建Hadoop集群,代码运行成功就能查看到相关数据。

MapReduce入门—— MapReduce概述 + WordCount案例实操

MapReduce入门(一)—— MapReduce概述

MapReduce知识点总览图
在这里插入图片描述

1.1 MapReduce 定义

MapReduce 是一个分布式运算程序的编程框架,是用户开发“基于 Hadoop 的数据分析应用”的核心框架。
MapReduce 核心功能是将用户编写的业务逻辑代码自带默认组件整合成一个完整的分布式运算程序,并发运行在一个 Hadoop 集群上。
在这里插入图片描述

1.2 MapReduce 优缺点

1.2.1 优点

1 )MapReduce 易于编程

它简单的实现一些接口, 就可以完成一个分布式程序, 这个分布式程序可以分布到大量廉价的 PC 机器上运行。也就是说你写一个分布式程序,跟写一个简单的串行程序是一模一样的。就是因为这个特点使得 MapReduce 编程变得非常流行。

2 ) 良好的扩展性

当你的计算资源不能得到满足的时候, 你可以通过简单的增加机器来扩展它的计算能力。

3 ) 高容错性

MapReduce 设计的初衷就是使程序能够部署在廉价的 PC 机器上, 这就要求它具有很高的容错性。比如其中一台机器挂了,它可以把上面的计算任务转移到另外一个节点上运行,不至于这个任务运行失败, 而且这个过程不需要人工参与, 而完全是由Hadoop内部完成的。

4 ) 适合 PB 级以上海量数据的离线处理

可以实现上千台服务器集群并发工作,提供数据处理能力。

1.2.2 缺点

1 ) 不擅长实时计算

MapReduce 无法像 MySQL 一样,在毫秒或者秒级内返回结果。

2 ) 不擅长流式计算

流式计算的输入数据是动态的, 而 MapReduce 的输入数据集是静态的, 不能动态变化。
这是因为 MapReduce 自身的设计特点决定了数据源必须是静态的。

3 ) 不擅长 DAG (有向无环图)计算

多个应用程序存在依赖关系,后一个应用程序的输入为前一个的输出。在这种情况下,MapReduce 并不是不能做, 而是使用后, 每个 MapReduce 作业的输出结果都会写入到磁盘,会造成大量的磁盘 IO,导致性能非常的低下。

1.3 MapReduce 核心编程思想

在这里插入图片描述

(1)分布式的运算程序往往需要分成至少 2 个阶段。
(2)第一个阶段的 MapTask 并发实例,完全并行运行,互不相干。
(3)第二个阶段的 ReduceTask 并发实例互不相干,但是他们的数据依赖于上一个阶段的所有 MapTask 并发实例的输出。
(4)MapReduce 编程模型只能包含一个 Map 阶段和一个 Reduce 阶段,如果用户的业务逻辑非常复杂,那就只能多个 MapReduce 程序,串行运行。
总结:分析 WordCount 数据流走向深入理解 MapReduce 核心思想。

1.4 MapReduce 进程

一个完整的 MapReduce 程序在分布式运行时有三类实例进程:
(1)MrAppMaster:负责整个程序的过程调度及状态协调。
(2)MapTask:负责 Map 阶段的整个数据处理流程。
(3)ReduceTask:负责 Reduce 阶段的整个数据处理流程。

1.5 官方 WordCount 源码

采用反编译工具反编译源码,发现 WordCount 案例有 Map 类、Reduce 类和驱动类。且数据的类型是 Hadoop 自身封装的序列化类型。

先下载官方源码:
在这里插入图片描述
下载下来是一个jar包:
在这里插入图片描述
如何查看里面的代码程序呢?
可以从网上下载一个反编译工具:
在这里插入图片描述
点击jd-gui.exe运行,显示如下界面:

在这里插入图片描述
将桌面上的源码jar包拖拽过来:
在这里插入图片描述
在这里插入图片描述
打开其中官方WordCount程序
在这里插入图片描述
详细剖析其中代码
在这里插入图片描述

1.6 常用数据 序列化类型

在这里插入图片描述

1.7 MapReduce 编程规范

用户编写的程序分成三个部分:Mapper、Reducer 和 Driver。

1.Mapper阶段

(1)用户自定义的Mapper要继承自己的父类
在这里插入图片描述

(2)Mapper的输入数据是KV对的形式(KV的类型可自定义)

p.s. K是这一行的偏移量,V是这一行的内容。

(3)Mapper中的业务逻辑写在map()方法中
在这里插入图片描述
(4)Mapper的输出数据是KV对的形式(KV的类型可自定义)
(5)map()方法(MapTask进程)对每一个<K,V>调用一次

2.Reducer阶段

(1)用户自定义的Reducer要继承自己的父类
在这里插入图片描述

(2)Reducer的输入数据类型对应Mapper的输出数据类型,也是KV
(3)Reducer的业务逻辑写在reduce()方法中
在这里插入图片描述

(4)ReduceTask进程对每一组相同k的<k,v>组调用一次reduce()方法

3.Driver阶段

相当于YARN集群的客户端,用于提交我们整个程序到YARN集群,提交的是封装了MapReduce程序相关运行参数的job对象

1.8 WordCount 案例实操

1.8.1 本地测试

1 ) 需求

在给定的文本文件中统计输出每一个单词出现的总次数
(1)输入数据
创建一个文件夹
在这里插入图片描述

里面写上想要测试的数据

Avengers Avengers
DC DC
Mavel Mavel
Iron_Man
Captain_America
Thor
Hulk
Black_Widow
Hawkeye
Black_Panther
Spider_Man
Doctor_Strange
Ant_Man
Vision
Scarlet_Witch
Winter_Soldier
Loki
Star_Lord
Gamora
Rocket_Raccoon
Groot

在这里插入图片描述

(2)期望输出数据
(涉及到输入的排序问题)

Ant_Man	1
Avengers	2
Black_Panther	1
Black_Widow	1
Captain_America	1
DC	2
Doctor_Strange	1
Gamora	1
Groot	1
Hawkeye	1
Hulk	1
Iron_Man	1
Loki	1
Mavel	2
Rocket_Raccoon	1
Scarlet_Witch	1
Spider_Man	1
Star_Lord	1
Thor	1
Vision	1
Winter_Soldier	1

2 ) 需求分析

按照 MapReduce 编程规范,分别编写 Mapper,Reducer,Driver。

在这里插入图片描述

3 ) 环境准备

(1)创建 maven 工程,MapReduceDemo

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
按照之前的修改成自己的Maven仓库,相关内容可参考:
HDFS的API环境准备小知识——Maven 安装与配置
在这里插入图片描述

然后将相关java编译器配成自己的版本
相关内容参考
【Maven报错】Error:java: 不再支持源选项 5。请使用 6 或更高版本。(JDK14版成功解决)

(2)在 pom.xml 文件中添加版本信息以及相关依赖

<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <encoding>UTF-8</encoding>
</properties>

<dependencies> 
    <dependency> 
        <groupId>org.apache.hadoop</groupId> 
        <artifactId>hadoop-client</artifactId> 
        <version>3.1.3</version> 
    </dependency> 
    <dependency> 
        <groupId>junit</groupId> 
        <artifactId>junit</artifactId> 
        <version>4.12</version> 
    </dependency> 
    <dependency> 
        <groupId>org.slf4j</groupId> 
        <artifactId>slf4j-log4j12</artifactId> 
        <version>1.7.30</version> 
    </dependency> 
</dependencies> 

在这里插入图片描述

(2)在项目的 src/main/resources 目录下,新建一个文件,命名为“log4j.properties”(打印相关日志)
在这里插入图片描述
在这里插入图片描述
在文件中填入:

log4j.rootLogger=INFO, stdout   
log4j.appender.stdout=org.apache.log4j.ConsoleAppender   
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout   
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n   
log4j.appender.logfile=org.apache.log4j.FileAppender   
log4j.appender.logfile.File=target/spring.log   
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout   
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n 

在这里插入图片描述

(3)创建包名:com.leokadia.mapreduce.wordcount
在这里插入图片描述
在这里插入图片描述
创建三个类
在这里插入图片描述

4 ) 编写程序

(1)编写 Mapper 类
package com.leokadia.mapreduce.wordcount;
/**
 * @author sa
 * @create 2021-05-05 10:46
 */
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;

/**
 * KEYIN, map阶段输入的key的类型:LongWritable
 * VALUEIN,map阶段输入value类型:Text
 * KEYOUT,map阶段输出的Key类型:Text
 * VALUEOUT,map阶段输出的value类型:IntWritable
 */
public class WordCountMapper extends Mapper<LongWritable, Text, Text, IntWritable> {
    private Text outK = new Text();
    private IntWritable outV = new IntWritable(1);  //map阶段不进行聚合

    @Override
    protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {

        // 1 获取一行
        // xxxxxx xxxxxx
        String line = value.toString();

        // 2 切割(取决于原始数据的中间分隔符)
        // xxxxxxx
        // xxxxxxx
        String[] words = line.split(" ");

        // 3 循环写出
        for (String word : words) {
            // 封装outk
            outK.set(word);

            // 写出
            context.write(outK, outV);
        }
    }
}

在这里插入图片描述

(2)编写 Reducer 类
package com.leokadia.mapreduce.wordcount;

/**
 * @author sa
 * @create 2021-05-05 10:47
 */
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;

import java.io.IOException;

/**
 * KEYIN, reduce阶段输入的key的类型:Text
 * VALUEIN,reduce阶段输入value类型:IntWritable
 * KEYOUT,reduce阶段输出的Key类型:Text
 * VALUEOUT,reduce阶段输出的value类型:IntWritable
 */
public class WordCountReducer extends Reducer<Text, IntWritable,Text,IntWritable> {
    private IntWritable outV = new IntWritable();

    @Override
    protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {

        int sum = 0;
        // xxxxxxx xxxxxxx ->(xxxxxxx,1),(xxxxxxx,1)
        // xxxxxxx, (1,1)
        // 将values进行累加
        for (IntWritable value : values) {
            sum += value.get();
        }

        outV.set(sum);

        // 写出
        context.write(key,outV);
    }
}

在这里插入图片描述

(3)编写 Driver 驱动类
package com.leokadia.mapreduce.wordcount;
/**
 * @author sa
 * @create 2021-05-05 10:47
 */
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;

import java.io.IOException;

public class WordCountDriver {

    public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {

        // 1 获取job
        Configuration conf = new Configuration();
        Job job = Job.getInstance(conf);

        // 2 设置jar包路径
        job.setJarByClass(WordCountDriver.class);

        // 3 关联mapper和reducer
        job.setMapperClass(WordCountMapper.class);
        job.setReducerClass(WordCountReducer.class);

        // 4 设置map输出的kv类型
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(IntWritable.class);

        // 5 设置最终输出的kV类型
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);

        // 6 设置输入路径和输出路径
        FileInputFormat.setInputPaths(job, new Path("D:\\\\input\\\\inputword"));
        FileOutputFormat.setOutputPath(job, new Path("D:\\\\hadoop\\\\output888"));

        // 7 提交job
        boolean result = job.waitForCompletion(true);

        System.exit(result ? 0 : 1);
    }
}

在这里插入图片描述

5 ) 本地测试

(1)需要首先配置好 HADOOP_HOME 变量以及 Windows 运行依赖

(2)在 IDEA 上运行程序
运行:
在这里插入图片描述
注意:此时如果再运行一遍,会报错
在这里插入图片描述
在mapreduce中,如果输出路径存在会报错

1.8.2 WordCount案例Debug调试

在以下几个地方打好断点
在这里插入图片描述
在这里插入图片描述

开始Debug
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
通过调试可以更清楚的理解机制
在这里插入图片描述

1.8.3 提交到集群测试

刚刚上面的代码是在本地运行的,是通过下载了hadoop相关的依赖,运用本地模式运行的
这样肯定是不行的,因为未来生产环境中,我们肯定是要在linux虚拟机上去运行

集群上测试

(1)用 maven 打 jar 包,需要添加的打包插件依赖

将下面的代码放在之前配置的依赖后面

<build> 
    <plugins> 
        <plugin> 
            <artifactId>maven-compiler-plugin</artifactId> 
            <version>3.6.1</version> 
            <configuration> 
                <source>1.8</source> 
                <target>1.8</target> 
            </configuration> 
        </plugin> 
        <plugin> 
            <artifactId>maven-assembly-plugin</artifactId> 
            <configuration> 
                <descriptorRefs> 
                    <descriptorRef>jar-with-dependencies</descriptorRef> 
                </descriptorRefs> 
            </configuration> 
            <executions> 
                <execution> 
                    <id>make-assembly</id> 
                    <phase>package</phase> 
                    <goals> 
                        <goal>single</goal> 
                    </goals> 
                </execution> 
            </executions> 
        </plugin> 
    </plugins> 
</build> 

在这里插入图片描述

注意:博主原来的配置是14后面你们会发现14其实hadoop不支持,所以应该配置为JDK8,我将放的代码都改成了8的配置哈。

注意:如果工程上显示红叉。在项目上右键->maven->Reimport 刷新即可。

(2)将程序打成 jar 包

在这里插入图片描述
打包完毕,生成jar包
在这里插入图片描述
去文件夹里查看一下
在这里插入图片描述
由于我们集群里面配置了相关依赖的内容,用上面的即可

(3)修改不带依赖的 jar 包名称为 wc.jar,并拷贝该 jar 包到 Hadoop 集群的/opt/module/hadoop-3.1.3 路径

将上面6kb的复制到桌面并改名
在这里插入图片描述
思考:
刚刚的程序中,我们写的路径是本地windows的路径
在这里插入图片描述
上传到linux环境后它其实没有这个路径,输入输出路径不存在,于是我们需要对它进行修改,改成对应的集群路径
如果想更灵活一点——根据传入的路径来确定输入的路径
回顾之前的
在这里插入图片描述

我们再创建一个wordcount2包,跟wordcount内容一致,就将输入输出路径修改了一下
在这里插入图片描述
对于新改的程序,先点clean把前面的删掉,再点package进行导包
在这里插入图片描述
在这里插入图片描述

将新的包按上面的操作更名wc.jar

(4)启动 Hadoop 集群

[leokadia@hadoop102 mapreduce]$ myhadoop.sh start
在这里插入图片描述
对于已启动好的集群,直接拖拽
在这里插入图片描述
在这里插入图片描述
jar包导入完毕!

在这里插入图片描述

先在HDFS集群中设置刚刚要wordcount的源文件
在集群中建一个Marvel文件夹
在这里插入图片描述

在文件夹中上传我们之前要wordcount的Marvel.txt源文件
在这里插入图片描述

在这里插入图片描述

(5)执行 WordCount 程序

[leokadia@hadoop102 hadoop-3.1.3]$ hadoop jar wc.jar com.leokadia.mapreduce.wordcount2.WordCountDriver /user/leokadia/Marvel /user/leokadia/output

你以为输入以上代码就是最后一步大功告成了?
不好意思,博主的java本地版本与hadoop的版本不兼容
在这里插入图片描述

博主本地装的14,当时在hadoop里面配置的8
博主本地的java版本
在这里插入图片描述
博主hadoop里面装的java版本
在这里插入图片描述
于是,然后经过查证,hadoop3.x目前只支持jdk1.8
博主只好将本地的jdk版本改成8

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

然后再重新生成jar包,导入jar包到集群,再重新运行程序

[leokadia@hadoop102 hadoop-3.1.3]$ hadoop jar wc.jar com.leokadia.mapreduce.wordcount2.WordCountDriver /Marvel /output
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
完结撒花!

以上是关于MapReduce入门1的主要内容,如果未能解决你的问题,请参考以下文章

Hadoop-MapReduce

Hadoop-MapReduce

MapReduce

不用怕面试官问MapReduce了

不用怕面试官问你MapReduce了

Hadoop那些事儿---MapReduce编程浅析