MapReduce 概述

放假回家了,笔记本没有环境,后面的图片源于网络

1.定义

MapReduce是一个分布式运算程序的编程框架。

MapReduce 核心功能是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的分布式运算程序,并发运行在一个 Hadoop 集群上。

2.优缺点

优点

1.MapReduce 易于编程

它简单的实现一些接口, 就可以完成一个分布式程序, 这个分布式程序可以分布到大量廉价的 PC 机器上运行。也就是说你写一个分布式程序,跟写一个简单的串行程序是一模一样的。

2.良好的扩展性

可以动态增加服务器,解决计算资源不够的问题

3.高容错性

任何一台机器挂掉,可以将任务转移到其他节点, 而且这个过程不需要人工参与, 而完全是由Hadoop内部完成的。

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

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

缺点

1.不擅长实时计算

MapReduce 无法像 MySQL 一样,在毫秒或者秒级内返回结果。不擅长快速响应。

2.不擅长流式计算

流式计算的输入数据是动态的, 而 MapReduce 的输入数据集是静态的, 不能动态变化。

Sparkstreaming和flink擅长流式计算

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

多个应用程序存在依赖关系,后一个应用程序的输入为前一个的输出。MapReduce可以做,但是中间的结果会存于磁盘,会造成大量的磁盘 IO,效率很低。

Spark擅长,中间结果基于内存。

3.MapReduce核心思想

MapReduce将计算过程分为两个阶段:Map和Reduce

1.Map阶段并行处理输入数据 –> 负责大任务分小任务

2.Reduce阶段对Map结果进行汇总 –> 负责汇总结果

需求

统计输入数据中每一个单词出现的次数,统计结果a-p一个文件,q-z一个文件。

核心思想

说明

1.Map阶段统计单词的时候,只会记录ranan:1,不会记录ranan:2,相同单词统计次数由Reduce阶段完成

2.MapReduce编程模型只能包含一个Map阶段和一个Reduce阶段。如果逻辑很复杂,只能多个MapReduce程序串行运行。也就是中间结果也会写入磁盘,所以说不擅长DAG有向无环图。

4.MapReduce进程

一个完整的MapReduce程序再分布式运行时有三类实例进程。

(1)MrAppMaster(是ApplicationMaster的子进程):负责整个程序的过程调度及状态协调。是运行一个job/任务/mr的老大

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

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

5.官方 WordCount 源码

案例的存储位置:/opt/module/hadoop-3.1.3/share/hadoop/mapreduce

下下来是个jar包,把jar包拖进编译工具里,通过反编译工具反编译源码。

发现 WordCount 案例

1.写在main方法里的叫driver

2.有 Map 类

3.Reduce 类

数据的类型是 Hadoop 自身封装的序列化类型。

6.常用数据序列化类型

7.MapReduce编程规范

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

7.1 Mapper阶段

1.用户自定义的Mapper要继承系统的Mapper类

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

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

3.Mapper中的业务逻辑写在map()方法中

4.Mapper的输出数据是KV对的形式(KV的类型可自定义)

5.MapTask进程对每一个<K,V>调用一次map()方法

7.2 Reduce阶段

1.用户自定义的Reducer要继承自己的父类

2.Reducer的输入类型对应Mapper的输出数据类型,也是KV。

3.Reduce的业务逻辑写在reduce()方法中

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

有多少个不同k,调用多少次reduce。

7.3 Driver阶段

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

8.WordCount 案例实操

本地测试

1.需求

再给定的文本文件中统计输出每一个单词出现的总次数

1).给定的输入数据 Hello.txt

2).期望输出数据(按首字母排序)

atguigu 2

banzhang 1

cls 2

hadoop 1

jiao 1

ss 2

xue 1

2.需求分析

Mapper阶段说明

1.转换成String的原因是,Text的API少,Java中对字符串处理的API多。

Driver阶段说明

1.指定job的输出结果路径,输出的文件不能提前存在

3.环境准备

1)创建maven工程MaoReduceDemo,修改成自己的Maven仓库.

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>

3)在项目的 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

4)创建包名 com.ranan.mapreduce.wordcount

在本包下创建三个类WordCountMapper、WordCountReducer、WordCountDriver

4.编写程序

始终关注输入与输出

编写Mapper类

说明

1.继承的类导入import org.apache.hadoop.mapreduce.Mapper;

2.Text导入的包是org.apache.hadoop.io

3.Mapper类

package com.ranan.mapreduce.wordcount;

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阶段不进行聚合,所以记为1 @Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException { // 1 获取一行 转化为string类型使用其api进行分割
// xxxxxx xxxxxx
String line = value.toString(); // 2 切割(取决于原始数据的中间分隔符)
// xxxxxxx
// xxxxxxx
String[] words = line.split(" "); // 3 循环写出
for (String word : words) {
//输出的类型需要时Text,但是当循环次数大时,不断创建态浪费资源。同理map的是每行调用,所以这里把该语句放在最外面。
//Text outk = new Text(); // 封装outk
outK.set(word); // context信息传递,把结果传递出去
context.write(outK, outV);
}
}
}

编写reducer类

类的结构同mapper方法相似。

抽象类 Context 用于与map和系统交互
run方法里{
setup:任务开始的初始化
核心方法reduce:每一种key会被调用一次
cleanup:任务结束后的收尾
}

reduce方法的重写。

map的输出是reduce的输入。

package com.ranan.mapreduce.wordcount;

//注意导入的包
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(); //values不是迭代器,类似与集合,values.iterator()获取其迭代器
@Override
protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException { int sum = 0; // xxxxxxx, (1,1)
// 将values进行累加
for (IntWritable value : values) {
//value.get() 将IntWritable转换成int类型
sum += value.get();
} outV.set(sum); // context信息传递,把结果传递出去
context.write(key,outV);
}
}

编写 Driver 驱动类

1.获取job

2.设置jar包路径

3.关联mapper和reducer

4.设置map输出的kv类型

5.设置最终输出的kV类型,有些程序没有reduce阶段,所以这里设置的是最终输出而不是reduce输出类型

6.设置输入路径和输出路径

7.提交job

package com.ranan.mapreduce.wordcount;

//注意导入的包
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\\output")); // 7 提交job
//正常提交job.submit()
boolean result = job.waitForCompletion(true); //可以监控并打印job信息
System.exit(result ? 0 : 1);
}
}

补充类型转换

String与Text转换

//Text转换成String
text.toString()
//String转换成Text
new Text outK = new Text();
outK.set(string)

Int与IntWritable转换

//IntWritable转换成int
text.get()
//Int转换成IntWritable
new IntWritable outK = new IntWritable();
outK.set(int)

5.本地测试

注意:此时如果再运行一遍,会报错。在mapreduce中,如果输出路径存在会报错

Debug

先执行WordCountDriver类的main方法,之后跳转到mapper类的run方法。

run方法里先执行setup初始化,在执行重写的map方法,最后执行cleanup方法。

进入到reducer类的run方法。

run方法里先执行setup初始化,在执行重写的reduce方法,最后执行cleanup方法。

提交到集群测试

本地运行是通过下载了hadoop相关的依赖,运行的代码。但是在生产环境中,是需要在linux虚拟机上的集群运行的。

如何在linux上运行,打包上传到虚拟机上。

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

将以下代码添加到pom.xml配置文件种

<project>

<build>
<plugins> <plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
//使用jdk1.8编译因为虚拟机上装的jdk是1.8版本的 <source>1.8</source>
<target>1.8</target>
</configuration>
</plugin> //把依赖也打包进去如pom.xml里的junit,org.apche.hadoop..等
//正常情况是不需要的,集群里已经有了
<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> </project>

2.将程序打成 jar 包

打包完毕,生成jar包

3.上传jar包到Hadoop 集群的/opt/module/hadoop-3.1.3 路径

注意

刚刚的程序中,我们写的路径是本地windows的路径,那么上传到集群该路径是肯定不存在的,所以还需要修改程序。

之前在集群中使用的命令,输入的路径和输出的路径是不确定的,是依靠命令行动态输入的。

[ranan@hadoop102]# hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar wordcount /wcinput /wcoutput

修改程序,对于新改的程序,先点clean把前面的删掉,再点package进行导包。

FileInputFormat.setInputPaths(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));

将6kb(不带依赖)的复制到桌面并改名wc.jar。

linux上先切换到jar包要上传的路径

cd /opt/Software/hadopp-3.1.3

拖拽上传

4.执行wc.jar包

首先需要输入的源文件

启动集群后,发现/input/word.txt可以作为输入文件

执行wc.jar程序

注意

打包用的JDK8,hadoop里面是JDK8,但是本地安装的是JDK11、Maven使用的是JDK11。

所以执行命令的时候会报错。

hadoop3.x目前只支持jdk1.8。修改版本到JDK8。

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

MapReduce01 概述的更多相关文章

  1. Hadoop| MapReduce01 概述

    概述 分布式运算程序: 优点:易于编程:良好扩展性:高容错性:适合PB级以上海量数据的离线处理: 缺点:不擅长实时计算:不擅长流式计算:不擅长DAG有向图计算: 核心思想: 1)分布式的运算程序往往需 ...

  2. 【AR实验室】ARToolKit之概述篇

    0x00 - 前言 我从去年就开始对AR(Augmented Reality)技术比较关注,但是去年AR行业一直处于偶尔发声的状态,丝毫没有其"异姓同名"的兄弟VR(Virtual ...

  3. Recurrent Neural Network系列1--RNN(循环神经网络)概述

    作者:zhbzz2007 出处:http://www.cnblogs.com/zhbzz2007 欢迎转载,也请保留这段声明.谢谢! 本文翻译自 RECURRENT NEURAL NETWORKS T ...

  4. Swift3.0服务端开发(一) 完整示例概述及Perfect环境搭建与配置(服务端+iOS端)

    本篇博客算是一个开头,接下来会持续更新使用Swift3.0开发服务端相关的博客.当然,我们使用目前使用Swift开发服务端较为成熟的框架Perfect来实现.Perfect框架是加拿大一个创业团队开发 ...

  5. .Net 大型分布式基础服务架构横向演变概述

    一. 业务背景 构建具备高可用,高扩展性,高性能,能承载高并发,大流量的分布式电子商务平台,支持用户,订单,采购,物流,配送,财务等多个项目的协作,便于后续运营报表,分析,便于运维及监控. 二. 基础 ...

  6. [C#] 进阶 - LINQ 标准查询操作概述

    LINQ 标准查询操作概述 序 “标准查询运算符”是组成语言集成查询 (LINQ) 模式的方法.大多数这些方法都在序列上运行,其中的序列是一个对象,其类型实现了IEnumerable<T> ...

  7. 【基于WinForm+Access局域网共享数据库的项目总结】之篇一:WinForm开发总体概述与技术实现

    篇一:WinForm开发总体概述与技术实现 篇二:WinForm开发扇形图统计和Excel数据导出 篇三:Access远程连接数据库和窗体打包部署 [小记]:最近基于WinForm+Access数据库 ...

  8. Java消息队列--JMS概述

    1.什么是JMS JMS即Java消息服务(Java Message Service)应用程序接口,是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送 ...

  9. [AlwaysOn Availability Groups]健康模型 Part 1——概述

    健康模型概述 在成功部署AG之后,跟踪和维护健康状况是很重要的. 1.AG健康模型概述 AG的健康模型是基于策略管理(Policy Based Management PBM)的.如果不熟悉这个特性,可 ...

随机推荐

  1. 洛谷 P4774 [NOI2018] 屠龙勇士

    链接:P4774 前言: 交了18遍最后发现是多组数据没清空/ll 题意: 其实就是个扩中. 分析过程: 首先发现根据题目描述的选择剑的方式,每条龙对应的剑都是固定的,有查询前驱,后继(在该数不存在前 ...

  2. (转)linux下错误的捕获:errno和strerror的使用,以及perror和strerror的区别

    经常在调用linux 系统api 的时候会出现一些错误,比方说使用open() write() creat()之类的函数有些时候会返回-1,也就是调用失败,这个时候往往需要知道失败的原因.这个时候使用 ...

  3. single-number-ii leetcode C++

    Given an array of integers, every element appears three times except for one. Find that single one. ...

  4. 【mysql2】下载安装mysql5.7版|不再更新系列

    一.下载MySQL 5.7 版 MySQL 5.7 版:官网下载地址 https://dev.mysql.com/downloads/windows/installer/5.7.html 下载的是50 ...

  5. C++ new 运算符 用法总结

    C++ new 运算符 用法总结 使用 new 运算符 分配内存 并 初始化 1.分配内存初始化标量类型(如 int 或 double),在类型名后加初始值,并用小括号括起,C++11中也支持大括号. ...

  6. 一维前缀和 连续数组和为k

    给定一个整数数组和一个整数 k ,请找到该数组中和为 k 的连续子数组的个数. 滑动窗口没办法解决有负数的情况 方法一: 预处理 前缀和 sum_ij = preSum[j] - preSum[i-1 ...

  7. NOIP模拟92&93(多校26&27)

    前言 由于太菜了,多校26 只改出来了 T1 ,于是直接并在一起写啦~~~. T0 NOIP 2018 解题思路 第一次考场上面写三分,然而我并不知道三分无法处理不是严格单峰的情况,但凡有一个平台都不 ...

  8. 数据库炸了----我就重启了一下啊(Communications link failure)

    重启数据库后,数据库大部分时间连不上了:连续请求不会报错,请求间隔时间稍微长一点就会报错报错如图: com.mysql.cj.jdbc.exceptions.CommunicationsExcepti ...

  9. git 回滚版本

    方法一.(回滚到原来的版本) 1.在gitlab上找到要恢复的版本号,如: bbdca96 2.在客户端执行如下命令(执行前,先将本地代码切换到对应分支): git reset --hard bbdc ...

  10. 新技能GET!在前端表格中花式使用异步函数的奥义

    背景 60年代时,操作系统中独立运行的单元通常是进程.但随着计算机技术的发展,人们发现在进程运行过程中,创建.撤销与切换都要花费较大的时空开销. 到了80年代为了解决这一问题,出现了更小的独立运行基本 ...