本地IDE编写执行MR+MR调优+数据倾斜

目录

一、环境准备

1、本地搭建hadoop环境

2、搭建maven

二、IDEA编写

 1、新建一个Maven 工程

2、修改配置仓库文件位置

3、编辑pom.xml 文件  代码如下

4、在data下新建一个wc.txt文件  内容如下

5、 新建MRMapper.java

6、新建MRReducer.java

7、新建MRDriver.java 文件

8、执行如下显示

 9、编写一个FileUtils .java 删除方法,当output文件夹存在时,对其先进行删除   

10、在MRDriver.java  中调用9中方法  

11、执行成功

三 、一些总结调整

1、对于各任务的运行解释

2、在如下处建立 log4j.properties  进行打印日志

四、一些调优点

1、Combiner(预聚合)

2、Hadoop数据倾斜  (面试点)

(1)什么是数据倾斜?表现?

(2)解决办法

(3)若导致导致数据倾斜的key(例如a)分布在很多不同的文件?如何解决?

 (4)Shuffle  优化

(5)一些面试思考题

五、思考题

1、combine不适合做avg,这是为什么?

2、hadoop有几种压缩格式,分别的优缺点与适用场景。

3、YARN参数调优

(1)yarn.nodemanager.resource.memory-mb

(2)yarn.scheduler.minimum-allocation-mb

(3)yarn.scheduler.maximum-allocation-mb

4、将上诉的IDEA例子打包运行在服务器

(1)使用IDEA将项目进行打包

(2)将jar包传入linux 

(3)使用命令对jar包进行运行

 (4)结果如下

5、map数和reduce数由什么决定?

(1) map的数量

   (2)reduece的数量

6、安装mysql5.7.11


一、环境准备

1、本地搭建hadoop环境

将hadoop相关文件放到目录下如下

配置环境变量

在终端输入hadoop version 如下

2、搭建maven

conf下setting文件使用国内镜像

<mirrors>
    <mirror>
      <id>nexus-aliyun</id>
      <mirrorOf>central</mirrorOf>
      <name>Nexus aliyun</name>
      <url>http://maven.aliyun.com/nexus/content/groups/public</url>
    </mirror>

  </mirrors>

环境变量

 在终端下输入mvn  -v

二、IDEA编写

 1、新建一个Maven 工程

 界面如下:

2、修改配置仓库文件位置

3、编辑pom.xml 文件  代码如下

<?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>MapReduce</artifactId>
    <packaging>jar</packaging>
    <version>1.0</version>

    <properties>
        <hadoop.version>3.1.3</hadoop.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>${hadoop.version}</version>
        </dependency>

        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-common</artifactId>
            <version>${hadoop.version}</version>
        </dependency>

        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-hdfs</artifactId>
            <version>${hadoop.version}</version>
        </dependency>
    </dependencies>

</project>

 然后点击maven 进行下载 如下

4、在data下新建一个wc.txt文件  内容如下

5、 新建MRMapper.java

代码如下:

package MR.wc;
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;

public class MRMapper extends Mapper<LongWritable, Text, Text, IntWritable> {
    Text k = new Text();
    IntWritable v = new IntWritable(1);

    @Override
    protected void setup(Context context) throws IOException, InterruptedException {
        System.out.println("Mapper.setup----------");
    }

    @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);
        }
    }

    @Override
    protected void cleanup(Context context) throws IOException, InterruptedException {
        System.out.println("Mapper.cleanup");
    }
}

6、新建MRReducer.java

package MR.wc;

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

import java.io.IOException;

public class MRReducer extends Reducer<Text, IntWritable, Text, IntWritable> {
    int sum;
    IntWritable v = new IntWritable();

    @Override
    protected void setup(Context context) throws IOException, InterruptedException {
        System.out.println("Mapper.setup__________");
    }

    @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);
    }

    @Override
    protected void cleanup(Context context) throws IOException, InterruptedException {
        System.out.println("Mapper.cleanup__________");
    }
}

7、新建MRDriver.java 文件

package MR.wc;

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;

public class MRDriver {
    public static void main(String[] args) throws Exception {
        String input ="data/wc.txt";
        String output ="out_mr_wc";
        final Configuration configuration = new Configuration();

        //1获取job对象
        final Job job = Job.getInstance(configuration);

        //2设置class
        job.setJarByClass(MRDriver.class);

        //3设置Mapper  和 Reducer
        job.setMapperClass(MRMapper.class);
        job.setReducerClass(MRReducer.class);

        //4设置Map端输出KV类型,即MRMapper的三四数据类型
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(IntWritable.class);

        //5设置Redu输出的KV类型,即MRReducer的三四数据类型
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);

        //6设置程序的输入输出路径
        FileInputFormat.setInputPaths(job,new Path(input));
        FileOutputFormat.setOutputPath(job, new Path(output));

        //7提交Job
       final boolean result = job.waitForCompletion(true);
        System.exit(result ? 0 : 1);
    }
}

8、执行如下显示

可在 output文件夹下找到 成功part 内容如下

 9、编写一个FileUtils .java 删除方法,当output文件夹存在时,对其先进行删除   

package MR.wc;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;

import java.io.IOException;

public class FileUtils {
    public static void deleteTarget(Configuration configuration,String output) throws IOException{
        final FileSystem fileSystem = FileSystem.get(configuration);
        final Path path = new Path(output);
        if (fileSystem.exists(path)){
            fileSystem.delete(path,true);
        }
    }
}

10、在MRDriver.java  中调用9中方法  

11、执行成功

三 、一些总结调整

1、对于各任务的运行解释

map 代表  输入行数

reducer  代表最后结果输出的行数 

2、在如下处建立 log4j.properties  进行打印日志

内容如下:

log4j.rootLogger=DEBUG, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

 在MRDriver main函数入口处添加  

BasicConfigurator.configure(); //自动快速地使用缺省Log4j环境

运行  打印日志成功

四、一些调优点

1、Combiner(预聚合)

介于map和reduce之间的一个reduce操作,但是它是运行在MapTask上的

作用:减少数据的网络传输,是一个非常重要的调优点

以下是未进行预聚合log

		Map input records=3
		Map output records=11
		Map output bytes=112
		Map output materialized bytes=140
		Input split bytes=104
		Combine input records=0
		Combine output records=0
		Reduce input groups=6
		Reduce shuffle bytes=140
		Reduce input records=11
		Reduce output records=6

添加combine 如下:

日志如下

Map input records=3
		Map output records=11
		Map output bytes=112
		Map output materialized bytes=82
		Input split bytes=104
		Combine input records=11
		Combine output records=6
		Reduce input groups=6
		Reduce shuffle bytes=82
		Reduce input records=6
		Reduce output records=6

2、Hadoop数据倾斜  (面试点)

(1)什么是数据倾斜?表现?

例如一个文件   里面有   a b c 三类单词,但是a有一亿个,b、c都是一个,对其做wc操作

这样可能会造成   Map1   99%    map2 100%   map3 100%

(2)解决办法

  使用combine

                        有    (a,1亿)

                                ( b,1)

                                 (c,1)

  以此  减少数据的网络传输,但是如果导致数据倾斜的key(例如a)分布在很多不同的文件,不同的mapper,这种方法就不太适合

比如 100个mapper   每个里面有1万个a   那么优化的粒度不是很大

(3)若导致导致数据倾斜的key(例如a)分布在很多不同的文件?如何解决?

   

方法一  局部聚合+全局聚合

第一次map:对于导致数据倾斜的key(a),加上一个随机数前缀

   1_a   2_a   3_a   。。。。等

   这样本来相同的key也会被分到多个reducer中进行局部聚合

   类似于将原本的串行变成并行

第二次map   去掉随机前缀,进行全局聚合

思想两次MR,第一次将key随机散列到不同的reducer进行处理,达到负载均衡的目的;

第二次再根据去掉的key的随机前缀,按照本来的key进行reduce处理

   方法二  增加reducer数,提高并行度

如下

比如   a  b  c  本来只有三个reduce,现在将reduce改为30个,也相当于处理a的reducer变多了

当设置为  0  时   ,reducer就不输出了  ,直接输出map结果

方法三    实现自定义分区

partitioner  :  按照某种规则  (可以自定义)对map输出的数据进行分区操作

默认的是HASHPartitioner 

顺序:map  -》 partitioner  -》reduce

根据数据分布情况,自定义散列函数,将key均匀分布到不同的reducer

如下:

 (4)Shuffle  优化

        1、map端 

                1.1 减少输入的文件个数,对小文件进行合并

                1.2 预聚合操作(combine)

       2、IO端

                数据传输进行压缩

      3、 reduce端

                3.1  设置map  reduce共存   

      在  mapred-site.xml  中设置,mapreduce.job.reduce.slowstart.completedmaps 默认是  0.05  

也就是说  map在执行5%时,开始为reduce进行申请资源,开始执行reduce操作

                3.2  尽量少使用reduce        

    reduce会产生大量的网络消耗,但该用还是得用

                3.3 增加reducer,提高并行度

       4、整体来看如何优化

                 4.1  合理的设置map数和reduce数

                 4.2   mr  on  yarn   yarn进行参数调优

                 4.3  加配置(机器、内存)

(5)一些面试思考题

 1、是否可以只要map,不要reduce ?

        可以

联系sql  where相当于map

 2、是否可以只有reduce,没有map?

可以

  

五、思考题

1、combine不适合做avg,这是为什么?

因为combine类似于reduce,所以他会先求一次平均值,然后将结果再传给reducer,然后reducer又会做一次平均值,可能造成结果不对。

2、hadoop有几种压缩格式,分别的优缺点与适用场景。

压缩格式优点缺点适用场景

snappy压缩

高速压缩速度和合理的压缩率;支持Hadoop native库。不支持split;压缩率比gzip要低;Hadoop本身不支持,需要安装;linux系统下没有对应的命令。当MapReduce作业的map输出的数据量比较大的时候,作为map到reduce的中间数据的压缩格式;或者作为一个MapReduce作业的输出和另外一个MapReduce作业的输入。

lzo压缩

压缩/解压速度也比较快,合理的压缩率;支持split,是Hadoop中最流行的压缩格式;支持Hadoop native库;可以在linux系统下安装lzop命令,使用方便。压缩率比gzip要低一些;hadoop本身不支持,需要安装;在应用中对lzo格式的文件需要做一些特殊处理(为了支持split需要建索引,还需要指定inputformat为lzo格式)。一个很大的文本文件,压缩之后还大于200M以上的可以考虑,而且单个文件越大,lzo优点越明显。

gzip压缩

压缩率比较高,而且压缩/解压速度也比较快;Hadoop本身支持,在应用中处理gzip格式的文件就和直接处理文本一样;有Hadoop native库;大部分linux系统都自带gzip命令,使用方便。不支持split当每个文件压缩之后在130M以内的,都可以考虑用gzip压缩格式。比如每天的日志压缩成一个gzip文件,运行MapReduce程序的时候通过多个gzip文件达到并发。对于处理这些文件的程序(如Hive、流、MapReduce程序)完全和文本处理一样,压缩之后原来的程序不需要做任何修改。

bzip2压缩

支持split;具有很高的压缩率,比gzip压缩率都高;Hadoop本身支持,但不支持native;在linux系统下自带bzip2命令,使用方便。压缩/解压速度慢;不支持native。适合对速度要求不高,但需要较高的压缩率的场景。可以作为MapReduce作业的输出格式;输出之后的数据比较大,处理之后的数据需要压缩存档减少磁盘空间并且以后数据用得比较少的情况;对单个很大的文本文件想压缩减少存储空间,同时又需要支持split,而且兼容之前的应用程序(即应用程序不需要修改)的情况。

3、YARN参数调优

Memory资源调度
yarn一般允许用户配置每个节点上可用的物理资源,注意,这里是"可用的",不是物理内存多少,就设置多少,因为一个服务器节点上会有若干的内存,一部分给yarn,一部分给hdfs,一部分给hbase;Member相关的配置如下:

(1)yarn.nodemanager.resource.memory-mb


设置该节点上yarn可使用的内存,默认为8G,如果节点内存资源不足8G,要减少这个值,yarn不会智能的去检测内存资源,一般这个设置yarn的可用内存资源

(2)yarn.scheduler.minimum-allocation-mb


单个任务最小申请物理内存量,默认1024MB,根据自己的业务设定

(3)yarn.scheduler.maximum-allocation-mb


单个任务最大申请物理内存量,默认为8291MB
 

4、将上诉的IDEA例子打包运行在服务器

(1)使用IDEA将项目进行打包

(2)将jar包传入linux 

(3)使用命令对jar包进行运行

[peizk@hadoop test]$ hadoop jar MapReduce2.jar peizk.WC /input/input.txt /output3

 (4)结果如下

5、map数和reduce数由什么决定?

(1) map的数量


map的数量通常是由hadoop集群的DFS块大小确定的,也就是输入文件的总块数,正常的map数量的并行规模大致是每一个Node是10~100个,对于CPU消耗较小的作业可以设置Map数量为300个左右,但是由于hadoop的每一个任务在初始化时需要一定的时间,因此比较合理的情况是每个map执行的时间至少超过1分钟。具体的数据分片是这样的,InputFormat在默认情况下会根据hadoop集群的DFS块大小进行分片,每一个分片会由一个map任务来进行处理,当然用户还是可以通过参数mapred.min.split.size参数在作业提交客户端进行自定义设置。还有一个重要参数就是mapred.map.tasks,这个参数设置的map数量仅仅是一个提示,只有当InputFormat 决定了map任务的个数比mapred.map.tasks值小时才起作用。同样,Map任务的个数也能通过使用JobConf 的conf.setNumMapTasks(int num)方法来手动地设置。这个方法能够用来增加map任务的个数,但是不能设定任务的个数小于Hadoop系统通过分割输入数据得到的值。当然为了提高集群的并发效率,可以设置一个默认的map数量,当用户的map数量较小或者比本身自动分割的值还小时可以使用一个相对交大的默认值,从而提高整体hadoop集群的效率。


   (2)reduece的数量


reduce在运行时往往需要从相关map端复制数据到reduce节点来处理,因此相比于map任务。reduce节点资源是相对比较缺少的,同时相对运行较慢,正确的reduce任务的个数应该是0.95或者1.75 *(节点数 ×mapred.tasktracker.tasks.maximum参数值)。如果任务数是节点个数的0.95倍,那么所有的reduce任务能够在 map任务的输出传输结束后同时开始运行。如果任务数是节点个数的1.75倍,那么高速的节点会在完成他们第一批reduce任务计算之后开始计算第二批 reduce任务,这样的情况更有利于负载均衡。同时需要注意增加reduce的数量虽然会增加系统的资源开销,但是可以改善负载匀衡,降低任务失败带来的负面影响。同样,Reduce任务也能够与 map任务一样,通过设定JobConf 的conf.setNumReduceTasks(int num)方法来增加任务个数。

6、安装mysql5.7.11

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值