大数据挖掘分析与应用 (七) MapReduce操作

MapReduce框架

一 MapReduce概述
优点:1.海量数据离线处理 2.易开发 3.易运行
缺点:实时流计算

MapReduce计算框架,基于磁盘(硬盘)IO输入输出
我从磁盘上读取数据到内存中,计算,得出结果放到磁盘

spark计算框架 ,基于内存的(内存条) 很短的时间内,数据是直接到内存的,计算,结果返回
在这里插入图片描述
MapReduce编程之工作流程:
1.将作业拆分为Map阶段和Reduce阶段
2.Map阶段:Map Tasks
3.Reduce 阶段:Reduce Tasks
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
WordCount案例:统计文件中每个单词出现的次数
工作中很多场景都是源于这个案例
需求:1. 文件小的情况,shell脚本就可以解决
例如
在这里插入图片描述
编写一个shell脚本,代码如下就可进行wordcount计算

cat hello.txt |sed 's/[,.:/!?]/ /g' |awk '{for(i=1;i<=NF;i++)array[$i]++;}END{for(i in array) print i,array[i]}'

权限不够要加执行权限!
在这里插入图片描述
在这里插入图片描述
2.如果文件内容很大,1GB,1TB等许多大文件,就需要mapreduce分布式计算框架了,例如歌曲top100,热点等等

数据处理形式

在这里插入图片描述
MapReduce的处理用Writable进行处理封装
intput和output的形式都是kv键值对
k是偏移量,v是数值,例如input中,<k1,v1>如下所示
第一行:<1,15> 数值包括空格
第二行<16,13>
第三行<29,13>

<k2,v2>表示单词和1

<k3,v3>表示单词和数量

MapReduce处理过程
在这里插入图片描述
开发用类:
inputformat getsplits()来得到偏移量 RecoredReader()
outputformat getRecordWrite来写出

数据文件是放在HDFS系统上的,以块的形式存储,默认128M
在这里插入图片描述
在这里插入图片描述

split:是MapReduce作业处理的数据块,是MapReduce中最小的计算单元,默认与block是默认对应的
在这里插入图片描述
本地编译步骤
1.控制台切换到项目目录下
2.使用Maven命令进行编译,最终编译成jar包
命令:mvn clean package -DskipTests
在这里插入图片描述
在这里插入图片描述
然后上传到服务器上
在这里插入图片描述
执行命令:

hadoop jar /home/lqz/data/jartest/0410-1.0-SNAPSHOT.jar org.example.
WordCountAPP hdfs://192.168.1.65:8020/hello.txt hdfs://192.168.1.65:8020/output/wc

在这里插入图片描述

hadoop fs -cat /output/wc/part-r-00000

在这里插入图片描述
代码如下

package org.example;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.Writable;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import java.io.IOException;

/**
 *   MapReduce 开发WordCount应用程序
 * */
public class WordCountAPP {
    
    
    /**
     * map 读取输入的文件
     * */
                                                 //int        String  String  int
    public static class MyMappter extends Mapper<LongWritable,Text,Text,LongWritable>{
    
    

        LongWritable one = new LongWritable(1);//第一次是1

        @Override           //相当于输入一行的数据
        protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
    
    

            LongWritable one = new LongWritable(1);//第一次是1

            //接受一行的数据,转换成字符串
            String lines = value.toString();
            //拆分
            String[] words = lines.split(" ");
            //放在contest进行输出
            for (String word:words
            ){
    
    
                //把map的结果输出
                context.write(new Text(word),one); //封装成 cat 1   pig 1
             }
        }
    }
    /**
     *  reduce处理,归并操作
     * */

    public static class MyReduce extends Reducer<Text,LongWritable,Text,LongWritable>{
    
    
        @Override                            //下面是迭代的lingwritable集合
        protected void reduce(Text key, Iterable<LongWritable> values, Context context) throws IOException, InterruptedException {
    
    
            long sum=0;
            for (LongWritable value:
                  values){
    
    
                //求key出现次数的总和
                sum+=value.get();//得到value的值  <cat,1>==>1
            }
            //把结果输出
            context.write(key,new LongWritable(sum));
        }
    }
    /**
     *  主方法
     *  Drive,封装了MapReduce作业的所有信息
     * */
    public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
    
    

        //创建一个连接configuration
        Configuration configuration= new Configuration();

        //准备工作,清理已经存在的文件
        Path outputpath=new Path(args[1]);
        FileSystem fileSystem=FileSystem.get(configuration);
        if (fileSystem.exists(outputpath)){
    
    
            fileSystem.delete(outputpath,true);
            System.out.println("输出目录存在,但是已经被删除了");
        }


        //创建一个job
        Job job=Job.getInstance(configuration,"wordcount");

        //设置处理那个类  告诉job要处理哪个类
        job.setJarByClass(WordCountAPP.class);

        //作业要处理数据的路径
        FileInputFormat.setInputPaths(job, new Path(args[0]));//路径是放到平台的,所以是通过传入参数形式

        //map处理的相关参数
        job.setMapperClass(MyMappter.class);  //找到自己处理的类
        job.setMapOutputKeyClass(Text.class);//设置输出的key类型
        job.setMapOutputValueClass(LongWritable.class);  //设置输出的value

        //设置reduce相关参数
        job.setReducerClass(MyReduce.class);
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(LongWritable.class);

        //设置combiner  逻辑跟reduce一样
        job.setCombinerClass(MyReduce.class);//相当于reduce后再加个reduce


        //作业处理完后,数据输出的路径,
        FileOutputFormat.setOutputPath(job,new Path(args[1]));

        //程序结束后,释放资源
        System.exit(job.waitForCompletion(true)?0:1); //wait有两个异长,classnotfound和interrupt

    }

}

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

MapReduce编程之Combine
1.本地的reduce
2.减少Map Tasks输出的数据量及数据网络传输量

如图所示:在一台机器上先把重复的加和计算,在分给下一台机器

在这里插入图片描述
在这里插入图片描述
多了combine的操作
在这里插入图片描述
Mapreduce编程之partitioner
partitioner决定Map Task输出的数据交由那个Reduce Task处理
默认:分发key的hash值对Reduce Task个数取模
在这里插入图片描述
案例
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43872169/article/details/105128457