Hadoop学习整理

前言

吃水不忘挖井人,我看的课是这个,课程带着安装,搞虚拟机,很详细,推荐一波

思维导图

Hadoop学习整理_第1张图片

环境

Hadoop102:

cd / 表示的是返回/

cd ~ 表示的是返回/home/fools

$HADOOP_HOME 配置的位置为/opt/module/hadoop-3.1.3

集群出现问题

如果某个集群namenode或datanode等出现异常,这时候只要先停掉每个集群sbin/stop-xxxxx.sh,删除每个服务器的data,logs目录rm -rf data/ logs/,然后再初始化hdfs namenode -format ,就可以复原了

hdfs存储路径

/opt/module/hadoop-3.1.3/data/dfs/data/current/BP-1116405649-192.168.10.102-1632297070587/current/finalized/subdir0/subdir0

hadoop概述

大数据主要解决海量数据的采集,存储,分析计算问题。

hadoop四大优势:

  • 高可靠性:底层维护多个数据副本,某单元出现问题,也不会导致数据丢失
  • 高扩展性:在集群间分配任务数据,可方便的扩展数以千计的节点
  • 高效性:mapreduce使hadoop并行工作,以加快任务处理速度
  • 高容错性: 能够自动将失败的任务重新分配

版本区别:
Hadoop学习整理_第2张图片

HDFS

hadoop distributed file system,分布式文件系统

  • NameNode:管理数据存储在什么位置;存储文件的元数据:文件名,文件目录结构,文件属性,以及每个文件所在的块列表和DataNode

  • DataNode:具体存储文件块数据,以及块数据的校验和

  • Secondary NameNode(2NN):每隔一段时间对NameNode元数据备份
    Hadoop学习整理_第3张图片

YARN

yet another resource negotiator,是一种资源协调者,是hadoop的资源管理器
Hadoop学习整理_第4张图片

  • resource manager是整个集群资源的管理者
  • NodeManager是单个节点服务器资源的管理者
  • client客户端提交作业给resouce manager,可以存储在多个
  • 每个Node manager上可以有多个container容器,相当于一个独立的服务器,每个container中包含applicatoinMaster(AM),是单个任务运行的老大

MapReduce

Hadoop学习整理_第5张图片

将任务交给很多人去做,然后将结果一起汇总在服务器

大数据生态体系

Hadoop学习整理_第6张图片

HDFS

Hadoop学习整理_第7张图片

概述

定义

分布式文件管理系统,适合一次写入,多次读出(可以追加)

优缺点

  • 优点

    高容错性:数据保存为多个副本,一个丢失后可以快速恢复

    适合处理大数据:可以处理文件规模很大,文件数量很多的文件

    可以构建在廉价机器上

  • 缺点

    不适合低延时访问

    无法高效搜索小文件

    不支持并发写入

    不支持文件随机修改,只支持追加

组成

  • NameNode:管理者master

所有HDFS的原数据名称都在这里存储

副本的配置策略

管理映射信息(哪一块数据存储在哪一块DataNode)

处理客户读写请求

  • DataNode:slave

存储实际的数据块

执行数据块的读写

  • Client:客户端

文件切分:上传HDFS之前,client会按照NameNode的块大小的要求(一般是128MB)进行切分,然后再上传

与NameNode交互,获取位置信息

与DataNode交互,获取或写入数据

提供一些命令来管理,访问HDFS

HDFS文件块大小普遍为128M,256M,这主要是和磁盘的传输速率有关,因为寻址时间为传输时间的1%是最佳状态。

如果块太大,寻址很快,传输较慢

如果块太小,寻址很慢,传输很快

Shell命令

其实hdfs的shell操作就是普通的shell操作前面加上hadoop fs - ,后面的内容和linux中差别不大

在使用xshell之前需要开启hadoop集群

`myhadoop.sh start`

or

`sbin/start-dfs.sh`

`sbin/start-yarn.sh`

举例:

想查看help:hadoop fs -help rm

创建文件:hadoop fs -mkdir /sanguo

上传

Hadoop学习整理_第8张图片

下载

Hadoop学习整理_第9张图片

另外还有其他的正常操作:

-ls -cat -cp -mv -tail -rm

Hadoop学习整理_第10张图片

HDFS API

其实万变不离其宗:

获取文件系统----创建目录----关闭资源

fs = FileSystem.get(uri,configuration,user);

fs.mkdirs(new Path("/xiyou/huaguoshan1"));

fs.close()

我们需要的操作只是获取文件系统的内容要写清楚,函数的参数传递清楚,关闭资源

package com.atguigu.hdfs;


import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;


// 正常的流程:获取文件系统----创建目录----关闭资源
public class HDFSclient {
    private FileSystem fs;

    @Before
    public void init() throws URISyntaxException, IOException, InterruptedException {
       // 链接的集群地址
       URI uri = new URI("hdfs://hadoop102:8020");

       // 创建一个配置文件
       Configuration configuration = new Configuration();

       // 用户
       String user = "fools";

       //获取用户客户端对象
       fs = FileSystem.get(uri,configuration,user);
   }

   @After
    public void close() throws IOException {
        // 关闭资源
        fs.close();
    }


    @Test
    public void testmkdir() throws URISyntaxException, IOException, InterruptedException {
        // 创建一个文件夹
        fs.mkdirs(new Path("/xiyou/huaguoshan1"));
    }
    
    @Test
    public void testPut() throws IOException {
        fs.copyFromLocalFile(false,false,
                new Path("C:\\Xshell7/sunwukong.txt"),new Path("hdfs://hadoop102/xiyou/huaguoshan"));

    }
    // 优先级:hdfs-default.xml-->hdfs-site.xml-->项目资源目录下resource配置-->代码里面配置
    @Test
    public void testDownload() throws IOException {
        fs.copyToLocalFile(false,new Path("hdfs://hadoop102/xiyou/huaguoshan"),new Path("D:\\sunhouzi.txt"));
    }


    @Test
    public void testRename() throws IOException {
        fs.rename(new Path("/wcinput/word.txt"),new Path("/wcinput/cc.txt"));
    }

    @Test
    public void testMv() throws IOException {
        fs.rename(new Path("/wcinput/cc.txt"),new Path("/tmp/sss.txt"));
    }

    @Test
    public void testRenameRoot() throws IOException {
        fs.rename(new Path("/wcinput"),new Path("/input"));
    }

    @Test
    public void testGetInfo() throws IOException {
        RemoteIterator<LocatedFileStatus> listFiles = fs.listFiles(new Path("/"), true);

        while (listFiles.hasNext()) {
            LocatedFileStatus fileStatus = listFiles.next();

            System.out.println(Arrays.toString(fileStatus.getBlockLocations()));
            System.out.println(fileStatus.getLen());

        }
    }

    @Test
    public void isContent() throws IOException {
        FileStatus[] listStatus = fs.listStatus(new Path("/"));

        for(FileStatus status:listStatus){
            if(status.isFile()){
                System.out.println("文件"+status.getPath().getName());
            }else{
                System.out.println("非文件"+status.getPath().getName());
            }
        }
    }

}

HDFS读写流程

HDFS写流程

Hadoop学习整理_第11张图片

  • 客户端 – NameNode
    • 客户端创建一个Distributed FileSystem,通过DFS
    • 请求上传
    • 响应(检查权限,目录情况后)
    • 请求上传某个文件,请求返回dataNode
    • 返回可以存储的dataNode节点(1. 本地节点;2.其他机架节点;3.其他机架另一个节点)
  • 客户端 – DataNode
    • 客户端创建FSDataOutputStream
    • 请求建立block传输通道(串行方式):Client请求3台中的一台DataNode 1(网络拓扑上的就近原则,如果都一样,则随机挑选一台DataNode)上传数据(本质上是一个RPC调用,建pipeline),DataNode 1收到请求会继续调用DataNode 2,然后DataNode 2调用DataNode 3,将整个pipeline建立完成,然后逐级返回客户端
    • 应答成功
    • 依次传输block(串行):Client开始往DataNode 1上传第一个block(先从磁盘读取数据放到一个本地内存缓存),以pocket为单位。写入的时候DataNode会进行数据校验,它并不是通过一个packet进行一次校验而是以chunk为单位进行校验(512byte)。DataNode 1收到一个packet就会传给DataNode 2,DataNode 2传给DataNode 3,DataNode 1每传一个pocket会放入一个应答队列等待应答

网络拓扑节点距离计算:

本质上就是到达同一共同祖先的距离总和。
Hadoop学习整理_第12张图片

而副本选择方面,首先第一个是本地的节点,第二个是附近机架的一个节点,第三个是第二个所在的机架的另一个节点,
Hadoop学习整理_第13张图片

HDFS读流程

Hadoop学习整理_第14张图片

  • 客户端通过DistributedFileSystem向NameNode请求下载文件,NameNode通过查询元数据,找到文件块所在的DataNode地址。

  • 挑选一台DataNode(就近原则,然后随机)服务器,请求读取数据。

  • DataNode开始传输数据给客户端(从磁盘里面读取数据输入流,以Packet为单位来做校验)。

  • 客户端以Packet为单位接收,先在本地缓存,然后写入目标文件。

NN和2NN工作机制

2NN主要用于辅助NN中FsImage和Edits的合并

FsImage文件是HDFS系统元数据的永久检查点,包含HDFS文件系统所有目录和文件inode的序列化信息

Edits文件存放所有更新操作,所有写操作执行时都会被首先记录在这里

内存:FsImage存储数据,Edits存储追加信息

开机的时候FsImage和Edits加载到内存中;关机的时候,将Edits追加到FsImage中;

但是这时候Edits很多可能导致速度慢,需要2NN帮助在开机的时间里合并

Hadoop学习整理_第15张图片

  • 第一阶段:NameNode启动

    1. 第一次启动NameNode格式化后,创建Fsimage和Edits文件。如果不是第一次启动,直接加载编辑日志和镜像文件到内存。

    2. 客户端对元数据进行增删改的请求。

    3. NameNode记录操作日志,更新滚动日志。

    4. NameNode在内存中对元数据进行增删改。

  • 第二阶段:Secondary NameNode工作

    1. Secondary NameNode询问NameNode是否需要CheckPoint。直接带回NameNode是否检查结果。

    2. Secondary NameNode请求执行CheckPoint。

    3. NameNode滚动正在写的Edits日志。

    4. 将滚动前的编辑日志和镜像文件拷贝到Secondary NameNode。

    5. Secondary NameNode加载编辑日志和镜像文件到内存,并合并。

    6. 生成新的镜像文件fsimage.chkpoint。

    7. 拷贝fsimage.chkpoint到NameNode。

    8. NameNode将fsimage.chkpoint重新命名成fsimage。

可以通过oiv oev 来查看fsimage文件和edits文件

2NN的checkpoint时间设置以及内存多大进行checkpoint的设置在hdfs-default.xml中

DataNode工作机制

Hadoop学习整理_第16张图片

DataNode每6小时向NameNode上报所有块信息

DataNode每3秒返回心跳信息,如果10分钟30秒没有收到心跳信息,就认为当前dataNode挂掉,不再向此dataNode传入或查找信息

DataNode的数据完整性一般使用CRC32进行校验

掉线的时限设置一般也是在hdfs-site.xml中

MapReduce概述

分布式运算程序的编程框架,mapreduce将用户编写的代码和自带默认组件整合成一个完整的分布式运算程序

分布式运算程序一般分为MapTask阶段,ReduceTask阶段,一个模型只能包含一个map阶段和一个reduce阶段,如果业务很复杂也只能穿行运行

  • 优点:
    • 易于编程,实现接口就可以完成分布式程序
    • 良好的扩展性,增加机器就可以
    • 高容错性,机器挂掉hadoop内部会自己将任务转移到其他节点
    • 适合大数据离线处理
  • 缺点:
    • 不擅长实时计算,秒级别无法达到
    • 不擅长流式计算,输入数据需要是静态的
    • 不擅长DAG,多个应用程序存在依赖关系,mapreduce性能很低,因为作业的输出结果总是会写入磁盘,会造成大量磁盘IO(spark擅长,spark的中间结果基于内存,hadoop中间结果基于磁盘)

MapReduce进程

一般包括三个实例进程:MrAppMaster,MapTask,ReduceTask

MrAppMaster:负责整个程序的过程调度和状态协调

MapTask:负责Map阶段数据处理流程

ReduceTask:负责Reduce阶段数据处理流程

MapReduce编程规范

一般程序分为Mapper,Reducer,Driver

mapper:

  1. 要继承自父类
  2. 输入参数与输出数据为KV对格式
  3. map()方法的每一个KV调用一次

输入的KV对K为当前的偏移量(位置),V为偏移量对应的字符串

package com.atguigu.mapreduce.wordcount;
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<LongWritable, Text, Text, IntWritable>{
	
	Text k = new Text();
	IntWritable v = new IntWritable(1);
	
	@Override
	protected void map(LongWritable key, Text value, Context context)	throws IOException, InterruptedException {
		
		// 1 获取一行
		String line = value.toString();
		
		// 2 切割
		String[] words = line.split(" ");
		
		// 3 输出
		for (String word : words) {
			
			k.set(word);
			context.write(k, v);
		}
	}
}

reducer:

  1. 要继承自父类
  2. 输入类型应该是父类的输出类型
  3. 每一组相同的K的只进行一次reduce方法
package com.atguigu.mapreduce.wordcount;
import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;

public class WordCountReducer extends Reducer<Text, IntWritable, Text, IntWritable>{

int sum;
IntWritable v = new IntWritable();

	@Override
	protected void reduce(Text key, Iterable<IntWritable> values,Context context) throws IOException, InterruptedException {
		
		// 1 累加求和
		sum = 0;
		for (IntWritable count : values) {
			sum += count.get();
		}
		
		// 2 输出
         v.set(sum);
		context.write(key,v);
	}
}

driver:

相当于Yarn集群的客户端,用于提交整个程序到Yarn集群

Hadoop序列化(serialisable)

序列化:把内存中的对象,转换成字节序列,存储在磁盘,以便于存储和网络传输

反序列化:将收到的字节序列或者是磁盘的持久化数据转换为内存的对象

hadoop的序列化相对于java的来说,校验信息更少,在网络中传输更加方便。

mapper的输出(reducer的输入)如果是多个值的bean对象,我们就需要自己序列化

实际实现需要新建类FlowBean继承自Writable接口,

Mapreduce 框架原理

Hadoop学习整理_第17张图片

inputFormat数据输入

切片与mapTask并行度

**数据块:**Block是HDFS物理上把数据分成一块一块。数据块是HDFS存储数据单位。

Hadoop学习整理_第18张图片

fileInputFormat切片机制

Hadoop学习整理_第19张图片

Hadoop学习整理_第20张图片

CombineTextInputFormat切片机制

框架默认的TextInputFormat切片机制是对任务按文件规划切片,不管文件多小,都会是一个单独的切片,都会交给一个MapTask,这样如果有大量小文件,就会产生大量的MapTask,处理效率极其低下。

CombineTextInputFormat用于小文件过多的场景,它可以将多个小文件从逻辑上规划到一个切片中,这样,多个小文件就可以交给一个MapTask处理。

Hadoop学习整理_第21张图片

(1)虚拟存储过程:

将输入目录下所有文件大小,依次和设置的setMaxInputSplitSize值比较,如果不大于设置的最大值,逻辑上划分一个块。如果输入文件大于设置的最大值且大于两倍,那么以最大值切割一块;当剩余数据大小超过设置的最大值且不大于最大值2倍,此时将文件均分成2个虚拟存储块(防止出现太小切片)。

例如setMaxInputSplitSize值为4M,输入文件大小为8.02M,则先逻辑上分成一个4M。剩余的大小为4.02M,如果按照4M逻辑划分,就会出现0.02M的小的虚拟存储文件,所以将剩余的4.02M文件切分成(2.01M和2.01M)两个文件。

(2)切片过程:

(a)判断虚拟存储的文件大小是否大于setMaxInputSplitSize值,大于等于则单独形成一个切片。

(b)如果不大于则跟下一个虚拟存储文件进行合并,共同形成一个切片。

(c)测试举例:有4个小文件大小分别为1.7M、5.1M、3.4M以及6.8M这四个小文件,则虚拟存储之后形成6个文件块,大小分别为:

1.7M,(2.55M、2.55M),3.4M以及(3.4M、3.4M)

最终会形成3个切片,大小分别为:

(1.7+2.55)M,(2.55+3.4)M,(3.4+3.4)M

shuffle机制

shuffle是map方法之后,reduce方法之前的数据处理过程

map输出后,先进行分区再进入环形缓冲区
Hadoop学习整理_第22张图片

partition分区

partition分区是指在map结束之后,将统计结果按照条件输出到不同的文件中

默认partition按照key的hashcode对reduceTask的个数去摸得到的
Hadoop学习整理_第23张图片

我们可以自定义分区,但是需要在driver类中设置好job.set,否则不会生效

Hadoop学习整理_第24张图片

需要注意的是:

Hadoop学习整理_第25张图片

排序

MapTask和ReduceTask都会对key进行排序,属于hadoop的默认行为

map阶段的排序:

mapTask的处理结果暂时放在环形缓冲区

环形缓冲区使用了80%之后,开始反向写(提高效率),对缓冲区中的数据进行快速排序,(这里可以加入combiner功能)并将结果写出在磁盘上

当所有数据处理完毕后,对磁盘的所有文件进行归并排序(归并排序之后可以再做一次combiner)

Hadoop学习整理_第26张图片

reduceTask阶段的排序

reduce会自己拉取mapTask的数据文件到自己的内存中,当文件太大,会存在磁盘中

所有数据拷贝完成后,ReduceTask统一对内存和磁盘上的所有数据进行一次归并排序
Hadoop学习整理_第27张图片

如果key是一个bean对象?

实现bean对象需要重写writable接口,为了让bean对象作为key可以排序,需要实现WriteableComparable接口重写compareTo方法

combiner功能

combiner属于mapper和reducer之外,combiner组件的父类是reducer

combiner的意义在于对MapTask输出进行局部汇总,减少网络传输量

combiner不能影响业务逻辑(不能提前求平均)

如果没有reducer阶段,则combiner不存在

Hadoop学习整理_第28张图片

自定义Combiner实现步骤(一般来说直接set reducer.class就可以实现,不需要手动写)

(a)自定义一个Combiner继承Reducer,重写Reduce方法

public class WordCountCombiner 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;
        for (IntWritable value : values) {
            sum += value.get();
        }
     
        outV.set(sum);
     
        context.write(key,outV);
    }
}

(b)在Job驱动类中设置:

job.setCombinerClass(WordCountCombiner.class);

OutputFormat数据输出

hadoop如果向输出数据到MySQL,HBASE等等,需要自己定义一 个类继承FileOutputFormat,改写RecordWriter

MapReduce工作机制

Hadoop学习整理_第29张图片

​ (1)Read阶段:MapTask通过InputFormat获得的RecordReader,从输入InputSplit中解析出一个个key/value。

​ (2)Map阶段:该节点主要是将解析出的key/value交给用户编写map()函数处理,并产生一系列新的key/value。

​ (3)Collect收集阶段:在用户编写map()函数中,当数据处理完成后,一般会调用OutputCollector.collect()输出结果。在该函数内部,它会将生成的key/value分区(调用Partitioner),并写入一个环形内存缓冲区中。

​ (4)Spill阶段:即“溢写”,当环形缓冲区满后,MapReduce会将数据写到本地磁盘上,生成一个临时文件。需要注意的是,将数据写入本地磁盘之前,先要对数据进行一次本地排序,并在必要时对数据进行合并、压缩等操作。

​ 溢写阶段详情:

​ 步骤1:利用快速排序算法对缓存区内的数据进行排序,排序方式是,先按照分区编号Partition进行排序,然后按照key进行排序。这样,经过排序后,数据以分区为单位聚集在一起,且同一分区内所有数据按照key有序。

​ 步骤2:按照分区编号由小到大依次将每个分区中的数据写入任务工作目录下的临时文件output/spillN.out(N表示当前溢写次数)中。如果用户设置了Combiner,则写入文件之前,对每个分区中的数据进行一次聚集操作。

​ 步骤3:将分区数据的元信息写到内存索引数据结构SpillRecord中,其中每个分区的元信息包括在临时文件中的偏移量、压缩前数据大小和压缩后数据大小。如果当前内存索引大小超过1MB,则将内存索引写到文件output/spillN.out.index中。

​ (5)Merge阶段:当所有数据处理完成后,MapTask对所有临时文件进行一次合并,以确保最终只会生成一个数据文件。

​ 当所有数据处理完后,MapTask会将所有临时文件合并成一个大文件,并保存到文件output/file.out中,同时生成相应的索引文件output/file.out.index。

​ 在进行文件合并过程中,MapTask以分区为单位进行合并。对于某个分区,它将采用多轮递归合并的方式。每轮合并mapreduce.task.io.sort.factor(默认10)个文件,并将产生的文件重新加入待合并列表中,对文件排序后,重复以上过程,直到最终得到一个大文件。

​ 让每个MapTask最终只生成一个数据文件,可避免同时打开大量文件和同时读取大量小文件产生的随机读取带来的开销。

Hadoop学习整理_第30张图片

​ (1)Copy阶段:ReduceTask从各个MapTask上远程拷贝一片数据,并针对某一片数据,如果其大小超过一定阈值,则写到磁盘上,否则直接放到内存中。

​ (2)Sort阶段:在远程拷贝数据的同时,ReduceTask启动了两个后台线程对内存和磁盘上的文件进行合并,以防止内存使用过多或磁盘上文件过多。按照MapReduce语义,用户编写reduce()函数输入数据是按key进行聚集的一组数据。为了将key相同的数据聚在一起,Hadoop采用了基于排序的策略。由于各个MapTask已经实现对自己的处理结果进行了局部排序,因此,ReduceTask只需对所有数据进行一次归并排序即可。

​ (3)Reduce阶段:reduce()函数将计算结果写到HDFS上。

ReduceTask并行度决定机制

手动设置:job.setNumReduceTasks(4)

ReduceTask数量过少,数量过多都会影响性能
Hadoop学习整理_第31张图片

join的多种应用

我们可以选择在map端或者reduce端进行join

reduce join:

首先需要将两个不同的表放到一个bean中,作为map阶段的输出(针对不同的文件进行不同的处理),并且增加一个flag标签,方便reduce阶段的判断

然后在reduce阶段进行判断,根据不同的flag标签进行不同的操作

reduce阶段的join在reduce阶段处理压力很大,map阶段负载低,资源利用率不高,容易产生数据倾斜

Hadoop学习整理_第32张图片

map阶段join

在map阶段的setup中循环读取文件,将一个表的内容缓存在hashmap中,在map阶段进行两个表的匹配,拼接
Hadoop学习整理_第33张图片

ETL数据清洗

hadoop的数据清洗仅仅需要mapper程序就可以,符合要求就输出,不符合就直接reture

所以我们需要job.setNumReduceTask(0)

总结!!!

1)输入数据接口:InputFormat

(1)默认使用的实现类是:TextInputFormat

(2)TextInputFormat的功能逻辑是:一次读一行文本,然后将该行的起始偏移量作为key,行内容作为value返回。

(3)CombineTextInputFormat可以把多个小文件合并成一个切片处理,提高处理效率。

2)逻辑处理接口:Mapper

用户根据业务需求实现其中三个方法:map() setup() cleanup ()

3)Partitioner分区

(1)有默认实现 HashPartitioner,逻辑是根据key的哈希值和numReduces来返回一个分区号;key.hashCode()&Integer.MAXVALUE % numReduces

(2)如果业务上有特别的需求,可以自定义分区。

4)Comparable排序

(1)当我们用自定义的对象作为key来输出时,就必须要实现WritableComparable接口,重写其中的compareTo()方法。

(2)部分排序:对最终输出的每一个文件进行内部排序。

(3)全排序:对所有数据进行排序,通常只有一个Reduce。

(4)二次排序:排序的条件有两个。

5)Combiner合并

Combiner合并可以提高程序执行效率,减少IO传输。但是使用时必须不能影响原有的业务处理结果。

6)逻辑处理接口:Reducer

用户根据业务需求实现其中三个方法:reduce() setup() cleanup ()

7)输出数据接口:OutputFormat

(1)默认实现类是TextOutputFormat,功能逻辑是:将每一个KV对,向目标文本文件输出一行。

(2)用户还可以自定义OutputFormat。

数据压缩

Hadoop学习整理_第34张图片

在driver中设置

		// 开启map端输出压缩
		conf.setBoolean("mapreduce.map.output.compress", true);

		// 设置map端输出压缩方式
		conf.setClass("mapreduce.map.output.compress.codec", BZip2Codec.class,CompressionCodec.class);
		// 设置reduce端输出压缩开启
		FileOutputFormat.setCompressOutput(job, true);

		// 设置压缩的方式
	    FileOutputFormat.setOutputCompressorClass(job, BZip2Codec.class); 
//	    FileOutputFormat.setOutputCompressorClass(job, GzipCodec.class); 
//	    FileOutputFormat.setOutputCompressorClass(job, DefaultCodec.class); 

YARN

基础架构

ResouceManeger是整个集群资源的老大

NodeManager是单节点资源的老大

ApplicationMaster是每一个作业资源的老大

Container是相应资源的容器
Hadoop学习整理_第35张图片

Yarn的工作机制

这张图也显示了MapReduce和Yarn的合作关系

Hadoop学习整理_第36张图片

  1. MR程序提交到客户端所在的节点。

  2. YarnRunner向ResourceManager申请一个Application。

  3. RM将该应用程序的资源路径返回给YarnRunner。

  4. 该程序将运行所需资源提交到HDFS上。

  5. 程序资源提交完毕后,申请运行mrAppMaster。

  6. RM将用户的请求初始化成一个Task。

  7. 其中一个NodeManager领取到Task任务。

  8. 该NodeManager创建容器Container,并产生MRAppmaster。

  9. Container从HDFS上拷贝资源到本地。

  10. MRAppmaster向RM 申请运行MapTask资源。

  11. RM将运行MapTask任务分配给另外两个NodeManager,另两个NodeManager分别领取任务并创建容器。

  12. MR向两个接收到任务的NodeManager发送程序启动脚本,这两个NodeManager分别启动MapTask,MapTask对数据分区排序。

  13. MrAppMaster等待所有MapTask运行完毕后,向RM申请容器,运行ReduceTask。

  14. ReduceTask向MapTask获取相应分区的数据。

  15. 程序运行完毕后,MR会向RM申请注销自己。

HDFS和MapReduce的关联
Hadoop学习整理_第37张图片

Yarn调度器和调度算法

主要三种:FIFO,容量,公平

FIFO不支持多队列

容量和公平的相同点

Hadoop学习整理_第38张图片

不同点

在这里插入图片描述

容量调度器
Hadoop学习整理_第39张图片

公平调度器
Hadoop学习整理_第40张图片

Hadoop学习整理_第41张图片

Yarn常用命令

1.5.1 yarn application查看任务

(1)列出所有Application:

[atguigu@hadoop102 hadoop-3.1.3]$ yarn application -list
2021-02-06 10:21:19,238 INFO client.RMProxy: Connecting to ResourceManager at hadoop103/192.168.10.103:8032
Total number of applications (application-types: [], states: [SUBMITTED, ACCEPTED, RUNNING] and tags: []):0
                Application-Id	    Application-Name	    Application-Type	      User	     Queue	             State	       Final-State	       Progress	                       Tracking-URL

(2)根据Application状态过滤:yarn application -list -appStates (所有状态:ALL、NEW、NEW_SAVING、SUBMITTED、ACCEPTED、RUNNING、FINISHED、FAILED、KILLED)

[atguigu@hadoop102 hadoop-3.1.3]$ yarn application -list -appStates FINISHED
2021-02-06 10:22:20,029 INFO client.RMProxy: Connecting to ResourceManager at hadoop103/192.168.10.103:8032
Total number of applications (application-types: [], states: [FINISHED] and tags: []):1
                Application-Id	    Application-Name	    Application-Type	      User	     Queue	             State	       Final-State	       Progress	                       Tracking-URL
application_1612577921195_0001	          word count	           MAPREDUCE	   atguigu	   default	          FINISHED	         SUCCEEDED	           100%	http://hadoop102:19888/jobhistory/job/job_1612577921195_0001

(3)Kill掉Application:

[atguigu@hadoop102 hadoop-3.1.3]$ yarn application -kill application_1612577921195_0001
2021-02-06 10:23:48,530 INFO client.RMProxy: Connecting to ResourceManager at hadoop103/192.168.10.103:8032
Application application_1612577921195_0001 has already finished

1.5.2 yarn logs查看日志

(1)查询Application日志:yarn logs -applicationId

[atguigu@hadoop102 hadoop-3.1.3]$ yarn logs -applicationId application_1612577921195_0001

(2)查询Container日志:yarn logs -applicationId -containerId

[atguigu@hadoop102 hadoop-3.1.3]$ yarn logs -applicationId application_1612577921195_0001 -containerId container_1612577921195_0001_01_000001

1.5.3 yarn applicationattempt查看尝试运行的任务

(1)列出所有Application尝试的列表:yarn applicationattempt -list

[atguigu@hadoop102 hadoop-3.1.3]$ yarn applicationattempt -list application_1612577921195_0001
2021-02-06 10:26:54,195 INFO client.RMProxy: Connecting to ResourceManager at hadoop103/192.168.10.103:8032
Total number of application attempts :1
         ApplicationAttempt-Id	               State	                    AM-Container-Id	                       Tracking-URL
appattempt_1612577921195_0001_000001	            FINISHED	container_1612577921195_0001_01_000001	http://hadoop103:8088/proxy/application_1612577921195_0001/

(2)打印ApplicationAttemp状态:yarn applicationattempt -status

[atguigu@hadoop102 hadoop-3.1.3]$ yarn applicationattempt -status appattempt_1612577921195_0001_000001
2021-02-06 10:27:55,896 INFO client.RMProxy: Connecting to ResourceManager at hadoop103/192.168.10.103:8032
Application Attempt Report : 
	ApplicationAttempt-Id : appattempt_1612577921195_0001_000001
	State : FINISHED
	AMContainer : container_1612577921195_0001_01_000001
	Tracking-URL : http://hadoop103:8088/proxy/application_1612577921195_0001/
	RPC Port : 34756
	AM Host : hadoop104
	Diagnostics :

1.5.4 yarn container查看容器

​ (1)列出所有Container:yarn container -list

[atguigu@hadoop102 hadoop-3.1.3]$ yarn container -list appattempt_1612577921195_0001_000001
2021-02-06 10:28:41,396 INFO client.RMProxy: Connecting to ResourceManager at hadoop103/192.168.10.103:8032
Total number of containers :0
                  Container-Id	          Start Time	         Finish Time	               State	                Host	   Node Http Address

(2)打印Container状态: yarn container -status

[atguigu@hadoop102 hadoop-3.1.3]$ yarn container -status container_1612577921195_0001_01_000001
2021-02-06 10:29:58,554 INFO client.RMProxy: Connecting to ResourceManager at hadoop103/192.168.10.103:8032
Container with id 'container_1612577921195_0001_01_000001' doesn't exist in RM or Timeline Server.

注:只有在任务跑的途中才能看到container的状态

1.5.5 yarn node查看节点状态

​ 列出所有节点:yarn node -list -all

[atguigu@hadoop102 hadoop-3.1.3]$ yarn node -list -all
2021-02-06 10:31:36,962 INFO client.RMProxy: Connecting to ResourceManager at hadoop103/192.168.10.103:8032
Total Nodes:3
         Node-Id	     Node-State	Node-Http-Address	Number-of-Running-Containers
 hadoop103:38168	        RUNNING	   hadoop103:8042	                           0
 hadoop102:42012	        RUNNING	   hadoop102:8042	                           0
 hadoop104:39702	        RUNNING	   hadoop104:8042	                           0

生产调优

HDFS小文件过多

NameNode内存计算

​ 每个文件块大概占用150byte,一台服务器128G内存为例,能存储多少文件块呢?

​ 128 * 1024 * 1024 * 1024 / 150Byte ≈ 9.1亿

​ G MB KB Byte

当小文件过多,会占用过多的NameNode内存;每个文件都会开启一个MapTask,小文件过多会导致开启过多MapTask,启动时间比处理时间还长

  1. 将文件上传至HDFS前就先进行处理

  2. 我们可以使用HAR文件进行存档,HAR可以将小文件存入HDFS,并且可以透明访问。对于HDFS来说,仍然是很多小文件,但是对NameNode而言却是一个整体,这减少了NameNode的内存

  3. 开启uber模式,让同一个job的多个Task可以运行在一个JVM中,不用每个Task都开启JVM

MapReduce运行速度慢

  1. 计算机性能:CPU,内存充足,磁盘性能,网络带宽
  2. I/O操作优化:
    1. 数据倾斜
    2. Map运行时间太长,Reduce一直等待
    3. 小文件过多

数据倾斜优化方法:

mapper阶段

  1. 自定义分区,将同一个key对应的很多value打散,让其他reducer分担压力
  2. 减少磁盘IO,使用snappy压缩
  3. 减少溢写的次数(增加环形缓冲区大小,增加环形缓冲区的阈值),减少归并排序时候文件的数量
  4. 提前使用combiner
  5. 增加mapper的性能:增加MapTask内存上限,控制MapTask堆内存大小,增加默认MapTaskCPU核数

reduce阶段

  1. reduce阶段内存缓冲占据的内存比例,可以提高,进一步增加运算速度
  2. 内存缓冲中数据达到多少比例开始写入磁盘,提高这个值,让更多数据在内存中处理
  3. 增加reducer的性能:ReduceTask内存上线,ReduceTask堆内存大小,ReduceTask的CPU数量
  4. 调整当MapTask完成多少开始申请ReduceTask资源
  5. 不开启reducer任务

减少数据倾斜:

检查空值过多产生的数据倾斜:过滤空值;保留空值,自定义分区

map阶段提前处理

增加reduce个数

你可能感兴趣的:(大数据,hadoop,hdfs,big,data)