8、学习大数据笔记-MapReduce并行编程模型

一、MapReduce编程模型

- MapReduce是采用一种分而治之的思想设计出来的分布式计算框架
- 如一复杂或计算量大的任务,单台服务器无法胜任时,可将此大任务切分成一个个小的任务,小任务分别在不同的服务器上并行的执行;最终再汇总每个小任务的结果
- MapReduce由两个阶段组 成:Map阶段(切分成一个个小的任务)、Reduce阶段(汇总小任务的结果)。
复制代码

map()函数的输入是kv对,输出是一系列kv对,输出写入本地磁盘。
map 阶段由一定数量的Task 组成 包括 :
    1. 输入阶段格式解析:InputFormat
    2. 输入数据处理:Mapper
    3. 数据分组:Partitioner
reduce()函数的输入是kv对(即map的输出(kv对));输出是一系列kv对,最终写入HDFS
Reduce 阶段由一定数量的ReduceTask 组成:
    1. 数据远程拷贝
    2. 数据按照Key 排序
    3. 数据处理Reducer
    4. 数据输出格式OutputFormat
复制代码

- block对应一个分片split,一个split对应一个map task
- reduce task的个数由程序中编程指定
复制代码

MapReduce代码:

map代码

  package mapraduce;
    
    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 WordMap extends Mapper<LongWritable, Text,Text, IntWritable> {

    protected void map(LongWritable key, Text value, Context context)
            throws IOException, InterruptedException {
        String[] words = value.toString().split(" ");
        for (String word : words) {
            // 每个单词出现1次,作为中间结果输出
            context.write(new Text(word), new IntWritable(1));
        }
    }
}
复制代码

Reduce代码:

    package mapraduce;
    
    import org.apache.hadoop.io.IntWritable;
    import org.apache.hadoop.io.Text;
    import org.apache.hadoop.mapreduce.Reducer;
    
    import java.io.IOException;
    
    public class WordReduce extends Reducer<Text, IntWritable, Text, IntWritable> {
        /*
            key: hello
            value: List(1, 1, ...)
        */
        protected void reduce(Text key, Iterable<IntWritable> values,
                              Context context) throws IOException, InterruptedException {
            int sum = 0;
    
            for (IntWritable count : values) {
                sum = sum + count.get();
            }
            context.write(key, new IntWritable(sum));// 输出最终结果
        }
    }
复制代码

整体job代码:

    package mapraduce;
    
    import java.io.IOException;
    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.input.TextInputFormat;
    import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
    import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
    
    public class WordMain {
        public static void main(String[] args) throws IOException,
                ClassNotFoundException, InterruptedException {
            if (args.length != 2 || args == null) {
                System.out.println("please input Path!");
                System.exit(0);
            }
    
            Configuration configuration = new Configuration();
    
            Job job = Job.getInstance(configuration, WordMain.class.getSimpleName());
    
            // 打jar包
            job.setJarByClass(WordMain.class);
    
            // 通过job设置输入/输出格式
            //job.setInputFormatClass(TextInputFormat.class);
            //job.setOutputFormatClass(TextOutputFormat.class);
    
            // 设置输入/输出路径
            FileInputFormat.setInputPaths(job, new Path(args[0]));
            FileOutputFormat.setOutputPath(job, new Path(args[1]));
    
            // 设置处理Map/Reduce阶段的类
            job.setMapperClass(WordMap.class);
            job.setReducerClass(WordReduce.class);
            //如果map、reduce的输出的kv对类型一致,直接设置reduce的输出的kv对就行;如果不一样,需要分别设置map, reduce的输出的kv类型
         //   job.setMapOutputKeyClass(IntWritable.class);
            // 设置最终输出key/value的类型m
            job.setOutputKeyClass(Text.class);
            job.setOutputValueClass(IntWritable.class);
    
            // 提交作业
            job.waitForCompletion(true);
        }
    }

本地运行:修改mapred-site.xml中yarn改成local
    <configuration>
     <property>
    		<name>mapreduce.framework.name</name>
    		<value>local</value>
    	</property>
    </configuration>
    
配置输入输出路径:
    
    hdfs://node1:9000/data/customPartition.txt hdfs://node1:9000/num
复制代码

源文件:

结果:

打包运行:
复制代码

WEB UI查看结果:浏览器url地址:rm节点IP:18088(例如;node1:18088)
复制代码

二: Combiner

- map端本地聚合
- 不论运行多少次Combine操作,都不会影响最终的结果
- 并非所有的mr都适合combine操作,比如求平均值
- WordCountMap与WordCountReduce代码不变
- WordCountMain中,增加job.setCombinerClass(WordCountReduce.class);
复制代码

注:
    1.Combiner是MR程序中Mapper和Reduce之外的一种组件
    2.Combiner组件的父类就是Reducer
    3.Combiner和Reducer之间的区别在于运行的位置
    4.Reducer是每一个接收全局的Map Task 所输出的结果
    5.Combiner是在MapTask的节点中运行
    6.每一个map都会产生大量的本地输出,Combiner的作用就是对map输出的结果先做一次合并,以较少的map和reduce节点中的数据传输量
    7.Combiner的存在就是提高当前网络IO传输的性能,也是MapReduce的一种优化手段。
    8.实现自定义的Combiner
        1.因为源码中的Combiner是继承于Reducer,我们使用自己的Combiner就需要继承Reducer并重写reduce方法
        2.job中设置job.setCombinerClass(自定义Combiner的类.class)
    ps:需要注意一个点就是:Combiner就是一次Reducer类中reduce方法的实现,所以这里的KV需要和Reducer的KV是一致的
    实际开发一定是先实现Mapper之后,知道了KV,然后再根据需要实现自定义的Combiner中的KV
复制代码

三、 Shuffle

参考: MapReduce的shuffle过程详解(分片、分区、合并、归并。。。)

四、自定义分区Partition

- MapReduce自带的分区器是HashPartitioner
- 原理:先对map输出的key求hash值,再模上reducetask个数,根据结果,决定此输出kv对,被匹配的reduce取走

自定义分区功能,并设定reduce个数为4

    import org.apache.hadoop.io.IntWritable;
    import org.apache.hadoop.io.Text;
    import org.apache.hadoop.mapreduce.Partitioner;
    
    import java.util.HashMap;
    
    public class CustomPartitioner extends Partitioner<Text, IntWritable> {
        public static HashMap<String, Integer> dict = new HashMap<String, Integer>();
    
        static{
            dict.put("Dear", 0);
            dict.put("Bear", 1);
            dict.put("River", 2);
            dict.put("Car", 3);
        }
    
        public int getPartition(Text text, IntWritable intWritable, int i) {
            //
            int partitionIndex = dict.get(text.toString());
            return partitionIndex;
        }
    }
复制代码

五、二次排序

转载于:https://juejin.im/post/5d2ed5d351882575b86c187e

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值