大数据技术之hadoop(mapreduce)概述序列化(代码片段)

@从一到无穷大 @从一到无穷大     2022-12-12     463

关键词:

文章目录


1 MapReduce 概述

1.1 MapReduce 定义

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

1.2 MapReduce 优缺点

MapReduce优点

(1)MapReduce易于编程它简单的实现一些接口,就可以完成一个分布式程序,这个分布式程序可以分布到大量廉价的 PC机器上运行。也就是说你写一个分布式程序,跟写一个简单的串行程序是一模一样的。就是因为这个特点使得 MapReduce编程变得非常流行。
(2)良好的扩展性:当你的计算资源不能得到满足的时候,你可以通过简单的增加机器来扩展它的计算能力。
(3)高容错性:MapReduce设计的初衷就是使程序能够部署在廉价的 PC机器上,这就要求它具有很高的容错性。比如其中一台机器挂了,它可以把上面的计算任务转移到另外一个节点上运行,不至于这个任务运行失败, 而且这个过程不需要人工参与,而完全是由 Hadoop内部完成的。
(4)适合 PB级以上海量数据的离线处理:可以实现上千台服务器集群并发工作,提供数据处理能力。

MapReduce缺点

(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 自身封装的序列化类型。

1.6 常用数据序列化类型

Java类型Hadoop Writable 类型
BooleanBooleanWritable
ByteByteWritable
IntIntWritable
FloatFloatWritable
LongLongWritable
DoubleDoubleWritable
StringText
MapMapWritable
ArrayArrayWritable
NullNullWritable

1.7 MapReduce 编程规范

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

Mapper阶段
(1)用户自定义的Mapper要继承自己的父类
(2)Mapper的输入数据是KV对的形式(KV的类型可自定义)
(3)Mapper中的业务逻辑写在map()方法中
(4)Mapper的输出数据是KV对的形式(KV的类型可自定义)
(5)map()方法(MapTask进程)对每一个<K,V>调用一次

Reducer阶段
(1)用户自定义的Reducer要继承自己的父类
(2)Reducer的输入数据类型对应Mapper的输出数据类型,也是KV
(3)Reducer的业务逻辑写在reduce()方法中
(4)ReduceTask进程对每一组相同k的<k,v>组调用一次reduce()方法

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

1.8 WordCount 案例实操

1.8.1 本地测试

(1)需求
在给定的文本文件中统计输出每一个单词出现的总次数。原文件如下:

(2)需求分析
按照MapReduce 编程规范,分别编写Mapper,Reducer,Driver。

(3)环境准备
(a)创建maven 工程,MapReduceDemo
(b)在pom.xml 文件中添加如下依赖

<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>

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

(d)创建包名:com.Tom.mapreduce.wordcount

(4)编写程序
(a)编写 Mapper类

package com.Tom.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);

    @Override
    protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException 
        // 1 获取1行
        // hello hello
        String line = value.toString();

        // 2 切割
        // hello
        // hello
        String[] words = line.split(" ");

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

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

(b)编写Reducer类

package com.Tom.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();

    @Override
    protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException 
        int sum = 0;
        // hello, (1, 1)
        // 累加
        for (IntWritable value : values) 
            sum += value.get();
        

        outV.set(sum);

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

(b)编写Dirver类

package com.Tom.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("E:\\\\input\\\\inputword"));
        FileOutputFormat.setOutputPath(job, new Path("E:\\\\hadoop\\\\output1"));

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

        System.exit(result ? 0 : 1);
    

(5)本地测试
(a)需要首先配置好 HADOOP_HOME变量以及 Windows运行依赖
(b)在 IDEA/Eclipse上运行程序,结果如下:

1.8.2 提交到集群测试

(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>

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

(2)与本地测试相比,集群测试要修改Dirver类中的输入输出路径,修改之后将程序打成 jar包。

// 6 设置输入路径和输出路径
        FileInputFormat.setInputPaths(job, new Path(args[0]));
        FileOutputFormat.setOutputPath(job, new Path(args[1]));


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

(4)启动Hadoop 集群

[Tom@hadoop102 hadoop-3.1.3]$ sbin/start-dfs.sh
[Tom@hadoop103 hadoop-3.1.3]$ sbin/start-yarn.sh

(4)执行WordCount 程序

[Tom@hadoop102 hadoop-3.1.3]$ hadoop jar wc.jar com.Tom.mapreduce.wordcount2.WordCountDriver /input /output

2 Hadoop 序列化

2.1 序列化概述

什么是序列化?

序列化就是把内存中的对象,转换成字节序列 (或其他数据传输协议)以便于存储到磁盘(持久化)和网络传输。
反序列化就是将收到字节序列(或其他数据传输协议)或者是磁盘的持久化数据,转换成内存中的对象。

为什么要序列化?

一般来说,“活的”对象只生存在内存里,关机断电就没有了。而且“活的”对象只由本地的进程使用,不能被发送到网络上的另外一台计算机。 然而序列化可以存储“活的”对象,可以将“活的”对象发送到远程计算机。

为什么不用 Java的序列化?

Java的序列化是一个重量级序列化框架( Serializable),一个对象被序列化后,会附带很多额外的信息(各种校验信息, Header,继承体系等),不便于在网络中高效传输。所以Hadoop自己开发了一套序列化机制( Writable)。

Hadoop序列化特点:

(1)紧凑 高效使用存储空间。
(2)快速 读写数据的额外开销小。
(3)互操作 支持多语言的交互。

2.2 自定义 bean对象实现序列化接口( Writable)

在企业开发中往往常用的基本序列化类型不能满足所有需求,比如在 Hadoop框架内部传递一个 bean对象, 那么该对象就需要实现序列化接口。
具体实现 bean对象序列化步骤如下 7步 :
(1)必须实现 Writable接口;
(2)反序列化时,需要反射调用空参构造函数,所以必须有空参构造;

public FlowBean() 
        super();

(3)重写序列化方法

@Override
public void write(DataOutput out) throws IOException 
        out.writeLong(upFlow);
        out.writeLong(downFlow);
        out.writeLong(sumFlow);

(4)重写反序列化方法

@Override
    public void readFields(DataInput in) throws IOException 
        this.upFlow = in.readLong();
        this.downFlow = in.readLong();
        this.sumFlow = in.readLong();

(5)注意反序列化的顺序和序列化的顺序完全一致
(6)要想把结果显示在文件中,需要重写toString(),可用"\\t"分开,方便后续用。
(7)如果需要将自定义的bean 放在key 中传输,则还需要实现Comparable 接口,因为MapReduce 框中的Shuffle 过程要求对key 必须能排序。详见后面排序案例。

@Override
public int compareTo(FlowBean o) 
	// 倒序排列,从大到小
	return this.sumFlow > o.getSumFlow() ? -1 : 1;

2.3 序列化案例实操

需求

统计每一个手机号耗费的总上行流量、总下行流量、总流量
(1)输入数据

(2)输入数据格式

(3)期望输出数据格式

需求分析

编写MapReduce 程序

(1)编写流量统计的Bean 对象

package com.Tom.mapreduce.writable;

import org.apache.hadoop.io.Writable;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;

/**
 * 1. 定义类实现writable接口
 * 2. 重写序列化和反序列化方法
 * 3. 重写空参构造
 * 4. toString方法
 */
public class FlowBean implements Writable

    private long upFlow;    // 上行流量
    private long downFlow;  // 下行流量
    private long sumFlow;   // 总流量

    // 空参构造
    public FlowBean() 
    

    public long getUpFlow() 
        return upFlow;
    

    public void setUpFlow(long upFlow) 
        this.upFlow = upFlow;
    

    public long getDownFlow() 
        return downFlow;
    

    public void setDownFlow(long downFlow) 
        this.downFlow = downFlow;
    

    public long getSumFlow() 
        return sumFlow;
    

    public void setSumFlow(long sumFlow) 
        this.sumFlow = sumFlow;
    

    public void setSumFlow() 
        this.sumFlow = this.upFlow + this.downFlow;
    

    @Override
    public void write(DataOutput out) throws IOException 
        out.writeLong(upFlow);
        out.writeLong(downFlow);
        out.writeLong(sumFlow);
    查看详情  

大数据技术之hadoop(mapreduce)

文章目录MapReduce定义MapReduce核心思想WordCount案例Hadoop序列化MapReduce框架原理InputFormat数据输入MapReduce定义MapReduce是一个分布式运算程序的编程框架,是用户开发“基于Hadoop的数据分析应用”的核心框架。MapReduce核心功能是将... 查看详情

一文带你了解大数据技术之mapreduce

MapReduce概述1.MapReduce定义2.MapReduce优缺点2.1优点2.2缺点3.MapReduce核心思想4.MapReduce进程5.官方WordCount源码6.常用数据序列化类型7.MapReduce编程规范8.WordCount案例实操1.MapReduce定义MapReduce是一个分布式运算程序的编程框架,是用户开... 查看详情

大数据技术之hadoop(mapreduce)框架原理数据压缩(代码片段)

文章目录1MapReduce框架原理1.1InputFormat数据输入1.1.1切片与MapTask并行度决定机制1.1.2Job提交流程源码和切片源码详解1.1.3FileInputFormat切片机制1.1.4TextInputFormat1.1.5CombineTextInputFormat切片机制1.1.6CombineTextInputFormat案例实操1.2MapReduce工作流 查看详情

hadoop——hadoop优势组成大数据技术生态体系系统框架图

...(面试重点)1.5.1HDFS架构概述1.5.2YARN架构概述1.5.3MapReduce架构概述1.5.4HDFS、YARN、MapReduce三者关系1.6大数据技术生态体系1.7推荐系统框架图1.4Hadoop优势(4高)1)高可靠性 查看详情

hadoop技术之apachehadoop集群搭建

 Spark是大数据体系的明星产品,是一款高性能的分布式内存迭代计算框架,可以处理海量规模的数据。下面就带大家一起来开始学Spark!▼往期内容汇总:大数据导论Linux操作系统概述VMwareWorkstation虚拟机使用Linux... 查看详情

大数据hadoop|mapredece|yarn(代码片段)

...的文件系统数据和元数据HDFS核心属性HDFS简介HDFSshell操作MapReduce分而治之理解MapReduce思想分布式计算概念MapReduce介绍MapReduce产生背景MapReduce特点MapReduce局限性MapReduce实例进程MapReduce阶段组成MapReduce数据类型MapReduce官方示例计算圆... 查看详情

大数据技术之hadoop(hdfs)

第1章HDFS概述1.1HDFS产出背景及定义 1.2HDFS优缺点 1.3HDFS组成架构 1.4HDFS文件块大小(面试重点) 第2章HDFS的Shell操作(开发重点)1.基本语法 bin/hadoopfs具体命令ORbin/hdfsdfs具体命令dfs是fs的实现类。2.命令大全 [[em... 查看详情

大数据技术之hadoop(hdfs)概述shell操作api操作读写流程工作机制(代码片段)

文章目录1HDFS概述1.1HDFS产生背景及定义1.2HDFS优缺点1.3HDFS组成架构1.4HDFS文件块大小(面试重点)2HDFS的Shell操作(开发重点)2.1基本语法2.2命令大全2.3常用命令实操3HDFS的API操作3.1客户端环境准备3.2HDFS的API案例实操... 查看详情

大数据之二:hadoop与spark辨析

转载自知乎:https://www.zhihu.com/question/265684961)MapReduce:是一种离线计算框架,将一个算法抽象成Map和Reduce两个阶段进行处理,非常适合数据密集型计算。2)Spark:MapReduce计算框架不适合迭代计算和交互式计算,MapReduce是一种磁盘计... 查看详情

大数据之hadoop图解概述(代码片段)

文章目录🌹0写在开头☕1Hadoop是什么🚀2Hadoop发展历史(了解)💒3Hadoop三大发行版本(了解)🍎①ApacheHadoop(常用)🍏②ClouderaHadoop🍇③HortonworksHadoop☔️ 查看详情

10.sparksql之快速入门

...时代的来临,Hadoop风靡一时。为了使熟悉RDBMS但又不理解MapReduce的技术人员快速进行大数据开发,Hive应运而生。Hive是当时唯一运行在Hadoop上的SQL-on-Hadoop工具。??但是MapReduce计算过程中大量的中间磁盘落地过程消耗了大量的I/O,... 查看详情

大数据技术hadoop——yarn

...理其他的计算机调度问题)的操作系统平台,而mapreduce等运算程序则相当于运行 查看详情

大数据基础之hive——hive概述(代码片段)

...duktig666/knowledge背景学习完Hadoop,有没有感到编写一个MapReduce程序非常复杂 查看详情

大数据技术之hadoop入门

?第1章大数据概论1.1大数据概念 大数据概念如图2-1所示。 图2-1大数据概念 1.2大数据特点(4V) 大数据特点如图2-2,2-3,2-4,2-5所示 图2-2大数据特点之大量 图2-3大数据特点之高速 图2-4大数据特点之多样 图2-5大数据... 查看详情

hadoop技术之hdfsshell操作

 ▼往期内容汇总:大数据导论Linux操作系统概述VMwareWorkstation虚拟机使用Linux常用基础命令、系统命令ApacheHadoop概述ApacheHadoop集群搭建HDFS分布式文件系统基础一、HDFSshell命令行解释说明介绍命令行界面 (英语: command-line... 查看详情

大数据—hadoop(入门篇一)(代码片段)

...ff08;一)Hadoop是什么Hadoop组成HDFS架构概述YARN架构概述MapReduce架构概述Hadoop是什么Hadoop是一个由Apache基金会所开发的分布式系统基础架构主要解决,海量数据的存储和海量数据的分析计算问题广义上来说,Hadoop通常是... 查看详情

hadoop技术之hdfs工作流程与机制

 ▼往期内容汇总:大数据导论Linux操作系统概述VMwareWorkstation虚拟机使用Linux常用基础命令、系统命令ApacheHadoop概述ApacheHadoop集群搭建HDFS分布式文件系统基础Hadoop技术之HDFSshell操作一、HDFS集群角色与职责官方架构图 主角色&... 查看详情