MapReduce案例详解

执行MapReduce时必须启动hdfs、yarn(start-dfs.sh、start-yarn.sh)

MapReduce实例

wordcount

package mapreduce;

import java.io.IOException;
import java.io.Serializable;
import java.sql.Driver;

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 org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

public class WordCount {
    public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {

        //加载配置文件
        Configuration conf=new Configuration();
        //启动一个job  一个map  reduce程序  这里叫做一个job
        Job job=Job.getInstance(conf);

        //指定job运行的主类
        job.setJarByClass(Driver.class);

         //指定这个job的mapper类和reduce类
        job.setMapperClass(WordCountMapper.class);
        job.setReducerClass(WordCountReducer.class);

        //指定map的输出的key  和  value的类型
        //这里为什么还要指定     泛型的只在编译的时候有作用  运行会自动擦除   所以在这里需要指定一下
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(IntWritable.class);

        //指定reduce输出的key和value类型
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);

        //指定输入路径   需要统计词频的路径
        FileInputFormat.addInputPath(job, new Path("/in"));
        //添加输出路径
        FileOutputFormat.setOutputPath(job, new Path("/out02"));
        //提交job
        job.waitForCompletion(true);


    }
    /*
     * 分
     */
    /**
     * 统计单词词频:
     * 	map这里:
     * 		统计每一个小文件的单词词频
     * 		拆分出来没有一个单词   标记1   输出就可以   统计工作reduce上了
     * 输入:  k-v  这里的输入是框架帮你输入的   写死的  固定的内容
     * KEYIN, 输入的键的类型  在这里指的是偏移量------指的是每一行起始的偏移量    long
     * VALUEIN:输入的值的类型  在这里指的是一行的内容     string
     * 第一行:
     * 	KEYIN:0
     * VALUEIN:hadoop	hadoop	spark	mllib	sqoop
     * 输出:  k-v  取决于用户的业务
     * KEYOUT, 输出的键的类型     这里指的是单词  可以允许重复的    string
     * VALUEOUT  输出的值的类型  这里指的是1     int
     * @author aura-bd
     *我的数据map-----reduce中    你的程序执行的时候  可能map  reduce不在一台机器上
     *序列化和反序列化
     *	数据需要持久化或网络传输的时候    Serializable
    所以所有map短   reduce  传输的数据必须是经过序列化和反序列化的
     *但是hadoop中自定义了一套序列化和反序列化的接口:
     *	没有使用java中?因为java中的序列化和反序列化接口Serializable(将类结构一并可进行序列化和反序列化)  过于臃肿
     *Writable
     *long-----longWritable
     *int-----intwritable
     *double---doublewritable
     *float-----floatwritable
     *
     *null-----nullwritable
     *string-----text
     */
    public class WordCountMapper extends Mapper<LongWritable, Text, Text, IntWritable>{
        //重写map方法
        /**
         * key:输入的键  这里指的每一行的起始偏移量
         * value:指的输入的值   这里指的是没一行的内容
         * context:上下文对象   用于传输使用的      map----reduce中
         * 这个方法的调用频率:
         * 	每行调用一次  文本中有几行就调用几次
         * key:当前行的起始偏移量
         * value:当前行的内容    和key是一一对应的
         */
        @Override
        protected void map(LongWritable key,
                           Text value,
                           Context context)
                throws IOException, InterruptedException {
            //拿到每一行的内容  进行分割
            //将text---String
            String line = value.toString();
            //拆分单词
            String[] words = line.split("\t");
            //循环遍历每一个单词  进行打标机  1  发送给reduce进行统一统计
            for(String w:words){
                //参数1:key   参数2:value
                //String--text
                Text k=new Text(w);
                IntWritable v=new IntWritable(1);
                context.write(k, v);
            }

        }

    }
    /**
     * reduce输出结果:   单词----词频
     * 进行统计分析
     * @author aura-bd
     * 输入:     map输出的
     * KEYIN, map输出的key  指的就是单词          text
     * VALUEIN, map输出的value  指的就是1    IntWritable
     * 输出:      最终写出到文件的
     * KEYOUT, 输出的key的类型  这里指的就是单词     这里的key不可以重复的  text
     * VALUEOUT:输出的value的类型  这里指的就是总的词频   intwritable
     *
     */
    public class WordCountReducer extends Reducer<Text, IntWritable, Text, IntWritable>{
        /**
         * 这个方法的调用频率:每组调用一次     有几组会调用几次
         * 分组规则:
         * 	key相同的为一组
         * hello,1   hello,1 hadoop,1  hello,1
         * key:reduce输入的  这里指的是单词   每一组中的一个key
         * values:每一组中的所有value   <1,1,1>
         */
        @Override
        protected void reduce(Text key,
                              Iterable<IntWritable> values,
                              Context context) throws IOException, InterruptedException {
            //进行词频统计
            int sum=0;
            //循环变遍历values   求和
            for(IntWritable v:values){
                //v.get()  这个是将intwritable转换为int
                sum+=v.get();
            }
            context.write(key, new IntWritable(sum));
        }
    }
}


linux运行mapreduce jar包

执行jar包格式:Hadoop jar /home/hadoop/wc.jar 类的全限定名称 /wc/input /wc/output

注意:/wc/input 是存在的(放要测试的数据) /wc/output是不存在的

Hadoop jar /home/hadoop/wc.jar com.gh.mapreduce.Driver

Hadoop jar /home/hadoop/wc.jar wordcount 输入路径args[0] 输出路径args[1]

采用传参方式运行jar包时,程序运行的时候,传入的第一个参数封装在args的第一个元素(下标0),第二个参数封装在数组的第二个元素。

相应的jar包代码中,将输入、输出路径改为args数组:

FileInputFormat.addInputPath(job,new Path(args[0]));

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

结论

reduce后的结果是按照最终输出的key的字典顺序进行排序(默认升序)

MR编程套路图

FileInputFormat是抽象类,默认用TextFileInputFormat进行文件加载

RecordReader是抽象类,默认用LineRecordReader进行文件读取

shuffle过程:先分区,再排序,再分组

分区个数决定reduce端输出的文件的个数(对应多少台机器执行任务)

Maptask的并行度

并行度

同时运行的maptask的任务的个数,一个maptask肯定只运行在一台节点上

Maptask是什么?

运行map部分的任务,我们就叫做Maptask(Mapper类的并行度)

Maptask并行度应该和数据量相关

Maptask对应的是解决了多少数据量

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值