01 我们一起学大数据

今天老刘分享的是MapReduce知识点的第二部分,在第一部分中基本把MapReduce的工作流程讲述清楚了,现在就是对MapReduce零零散散的知识点进行总结,这次的内容大纲如下图:

02 需要谨记的知识点

第6点:自定义分区

在上篇文章里的第五点提到过这句话:分区用到了分区器,默认分区器是HashPartitioner,并且给出了相关代码,现在对分区详细介绍介绍。

分区原理

MapReduce有自带的默认分区器HashPartitioner,关键方法是利用getPartition()返回当前键值对的分区索引。

详细流程就是① 在环形缓冲区溢出写磁盘前,会将每个键值对kv,作为getPartition()的参数输入;

② 然后就会对键值对中的key求hash值,与MAX_VALUE按位与,再模上reduce task的个数,这里老刘假设reduce task的个数为4,那么map任务溢出的文件就会有4个分区,分区的index分别为0,1,2,3,那getPartition()的输出结果就是0,1,2,3。

③ 根据计算结果,就会决定出当前键值对KV,落入哪个分区,如果是0,就会落入到溢出文件的0分区里面。

④ 最后就会被相应的reduce通过http获得。

那讲完这个,就要说说自定义分区,为什么会有自定义分区?

因为MR用的是默认HashPartition分区,但是当前业务逻辑,不适用于HashPartition分区,就需要自己设计自定义分区。

这里就举个例子,自定义分区,使得文件中,分别以Dear、Bear、River、Car为键的键值对,分别落到index是0、1、2、3的分区中。

咱们先来分析分析它的逻辑,由于是自定义分区嘛!就需要自定义分区类,然后用这个类实现Partitioner接口,以及在getPartition()中实现分区逻辑,最后就是在main()中设置reduce个数为4,大致就是这样。

下面分享出关键代码:

  1. public class CustomPartitioner extends Partitioner<Text, IntWritable> {
  2. public static HashMap<String, Integer> dict = new HashMap<String, Integer>();
  3.  
  4. //定义每个键对应的分区index,使用map数据结构完成
  5. static{
  6. dict.put("Dear", 0);
  7. dict.put("Bear", 1);
  8. dict.put("River", 2);
  9. dict.put("Car", 3);
  10. }
  11.  
  12. public int getPartition(Text text, IntWritable intWritable, int i) {
  13. //Dear、Bear、River、Car分别落入到index是0,1,2,3的分区中
  14. int partitionIndex = dict.get(text.toString());
  15. return partitionIndex;
  16. }
  17. }

那么自定义分区就说完了,大家可以总结总结,自定义分区的步骤。


第7点:自定义Combiner

仔细看这张图的红色标记处,combine操作就发生在这个地方,它会把两个(Dear,1)变为1个(Dear,2)。

为什么要进行combine操作?

我们假设map中(Dear, 1)有1亿个,按原思路,map端需要存储1亿个(Dear, 1),然后将1亿个(Dear, 1)通过网络被reduce获得,然后再在reduce端进行汇总,这样做map端本地磁盘IO、数据从map端到reduce端传输的网络IO比较大,网络开销太大了。

所以我们就会需要想办法,能不能在reduce1从map1拉取1亿个(Dear, 1)之前,在map端就提前先做下reduce汇总,得到结果(Dear, 100000000),然后再将这个结果(一个键值对)传输到reduce1呢?那当然是可以的,这个操作就是combine操作。

combine操作具体流程如下:

当每个map任务的环形缓冲区添满80%,开始溢写磁盘文件。

在这个过程中会进行分区,每个分区内按键排序,如果设置了combine的话,就会继续进行combine操作,如果设置map输出压缩的话,就会进行压缩。

在合并溢写文件时,如果至少有3个溢写文件,并且设置了map端combine的话,会在合并的过程中触发combine操作;

但是若只有2个或1个溢写文件,则不触发combine操作(因为combine操作,本质上是一个reduce,需要启动JVM虚拟机,有一定的开销)

combine本质上也是reduce;因为自定义的combine类继承自Reducer父类

MR代码如下:

  1. //在main()中进行设置
  2. job.setCombinerClass(WordCountReduce.class)

MR的combine操作就讲得差不多了,大家还可以总结总结!


第8点:MR压缩

为什么会有MR压缩?

在MR中,为了减少磁盘IO及网络IO,可考虑在map端、reduce端设置压缩功能。

那么如何设置压缩功能呢?只需在main方法中,给Configuration对象增加如下设置即可:

  1. //开启map输出进行压缩的功能
  2. configuration.set("mapreduce.map.output.compress", "true");
  3. //设置map输出的压缩算法是:BZip2Codec,它是hadoop默认支持的压缩算法,且支持切分
  4. configuration.set("mapreduce.map.output.compress.codec", "org.apache.hadoop.io.compress.BZip2Codec");
  5. //开启job输出压缩功能
  6. configuration.set("mapreduce.output.fileoutputformat.compress", "true");
  7. //指定job输出使用的压缩算法
  8. configuration.set("mapreduce.output.fileoutputformat.compress.codec", "org.apache.hadoop.io.compress.BZip2Codec");

那MR压缩就差不多就讲完了,大家可以继续总结总结。


第9点:自定义InputFormat

老刘主要讲讲InputFormat的流程,老刘之前在MapReduce的第一篇文章中讲过,假设MR的输入文件有三个block:block1,block2,block3,每一个block对应一个split分片,每一个split对应一个map任务(map task)。

但是呢,没有讲如何把文件进行切分之类的问题,就直接给出来了,下面就是讲讲这些内容。

先说一点,MapReduce任务的输入文件一般是存储在HDFS里面,我们主要看map任务是如何从hdfs读取分片数据的部分。

这里会涉及三个关键的类:

① InputFormat输入格式类

② InputSplit输入分片类:getSplit(),InputFormat输入格式类将输入文件分成一个个分片InputSplit;每个Map任务对应一个split分片。

③ RecordReader记录读取器类:createRecordReader(),RecordReader(记录读取器)读取分片数据,一行记录生成一个键值对;传入map任务的map()方法,调用map()。

再说说为什么需要自定义InputFormat?

无论hdfs还是mapreduce,处理小文件都有损效率,实践中,又难免面临处理大量小文件的场景,那这个时候就需要采取一些解决办法。

小文件的优化无非以下几种方式:

① 在数据采集的时候,就将小文件或小批数据合成大文件再上传HDFS(SequenceFile方案)。

② 在业务处理之前,在HDFS上使用mapreduce程序对小文件进行合并;可使用自定义InputFormat实现。

③ 在mapreduce处理时,可采用CombineFileInputFormat提高效率。

我们可以采取第二步,自定义输入格式。老刘这次只能讲讲大概了,等老刘阅读源码水平变高,再来给大家好好讲讲。

03 知识点总结

好啦,今天的MapReduce内容就总结得差不多了,内容还是蛮多的,难点就是这个自定义InputFormat,老刘也只是讲了讲大概,等以后有空了,老刘看源码水平变高了,再看给大家好好讲讲。

最后,有事,就联系公众号:努力的老刘;没事,就和老刘一起好好写大数据。

我要进大厂之大数据MapReduce知识点(2)的更多相关文章

  1. 我要进大厂之大数据MapReduce知识点(1)

    01 我们一起学大数据 老刘今天分享的是大数据Hadoop框架中的分布式计算MapReduce模块,MapReduce知识点有很多,大家需要耐心看,用心记,这次先分享出MapReduce的第一部分.老 ...

  2. 我要进大厂之大数据ZooKeeper知识点(2)

    01 我们一起学大数据 接下来是大数据ZooKeeper的比较偏架构的部分,会有一点难度,老刘也花了好长时间理解和背下来,希望对想学大数据的同学有帮助,也特别希望能够得到大佬的批评和指点. 02 知识 ...

  3. 我要进大厂之大数据ZooKeeper知识点(1)

    01 让我们一起学大数据 老刘又回来啦!在实验室师兄师姐都找完工作之后,在结束各种科研工作之后,老刘现在也要为找工作而努力了,要开始大数据各个知识点的复习总结了.老刘会分享出自己的知识点总结,一是希望 ...

  4. 我要进大厂之大数据Hadoop HDFS知识点(1)

    01 我们一起学大数据 老刘今天开始了大数据Hadoop知识点的复习,Hadoop包含三个模块,这次先分享出Hadoop中的HDFS模块的基础知识点,也算是对今天复习的内容进行一次总结,希望能够给想学 ...

  5. 我要进大厂之大数据Hadoop HDFS知识点(2)

    01 我们一起学大数据 老刘继续分享出Hadoop中的HDFS模块的一些高级知识点,也算是对今天复习的HDFS内容进行一次总结,希望能够给想学大数据的同学一点帮助,也希望能够得到大佬们的批评和指点! ...

  6. 大数据 --> MapReduce原理与设计思想

    MapReduce原理与设计思想 简单解释 MapReduce 算法 一个有趣的例子:你想数出一摞牌中有多少张黑桃.直观方式是一张一张检查并且数出有多少张是黑桃? MapReduce方法则是: 给在座 ...

  7. 大数据核心知识点:Hbase、Spark、Hive、MapReduce概念理解,特点及机制

    今天,上海尚学堂大数据培训班毕业的一位学生去参加易普软件公司面试,应聘的职位是大数据开发.面试官问了他10个问题,主要集中在Hbase.Spark.Hive和MapReduce上,基础概念.特点.应用 ...

  8. 大白话详解大数据hive知识点,老刘真的很用心(2)

    前言:老刘不敢说写的有多好,但敢保证尽量用大白话把自己复习的内容详细解释出来,拒绝资料上的生搬硬套,做到有自己的了解! 1. hive知识点(2) 第12点:hive分桶表 hive知识点主要偏实践, ...

  9. 大白话详解大数据hive知识点,老刘真的很用心(3)

    前言:老刘不敢说写的有多好,但敢保证尽量用大白话把自己复习的内容详细解释出来,拒绝资料上的生搬硬套,做到有自己的了解! 1. hive知识点(3) 从这篇文章开始决定进行一些改变,老刘在博客上主要分享 ...

随机推荐

  1. 基于Docker的MySql

    MySQL Server安装教程 考虑到实际情况需要经常使用MySQL,为了方便大家能够快速基于Docker搭建MySQL这里以Linux下为例 进行说明,对于Windows用户来说直接通过查看官网H ...

  2. 第十七章 nginx动静分离和rewrite重写

    一.动静分离 动静分离,通过中间件将动静分离和静态请求进行分离:通过中间件将动态请求和静态请求分离,可以减少不必要的请求消耗,同时能减少请求的延时.通过中间件将动态请求和静态请求分离,逻辑图如下: 1 ...

  3. java安全编码指南之:ThreadPool的使用

    目录 简介 java自带的线程池 提交给线程池的线程要是可以被中断的 正确处理线程池中线程的异常 线程池中使用ThreadLocal一定要注意清理 简介 在java中,除了单个使用Thread之外,我 ...

  4. 「IDEA插件精选」安利一个IDEA骚操作:一键生成方法的序列图

    在平时的学习/工作中,我们会经常面临如下场景: 阅读别人的代码 阅读框架源码 阅读自己很久之前写的代码. 千万不要觉得工作就是单纯写代码,实际工作中,你会发现你的大部分时间实际都花在了阅读和理解已有代 ...

  5. vscode+WSL+Debug+Cmake+OpenGL

    网页版:https://www.cnblogs.com/Jay-CFD/p/12584334.html WSL安装 参考:https://www.cnblogs.com/Jay-CFD/p/60672 ...

  6. Java 中的 Lambda 表达式

    Lambda表达式 Lambda 表达式是 JDK1.8 的一个新特性,又称特殊的匿名内部类,可以取代大部分的匿名内部类,语法更简洁,可以写出更优雅的 Java 代码,可以极大地优化代码结构. Lam ...

  7. 字符串截取 slice,substr,substring 的区别

    一 只传递一个参数时候 let str = '0123456'; str.slice(5); //'56' str.substr(5); // '56' str.substring(5); // '5 ...

  8. selenium中的三种等待方式

    1.强制等待,采用的time.sleep,然后后面加上要等待的时间: 2.隐性等待implicitly_wait,隐性等待设定后,会对之后的所有代码生效,会在设定的时间之内,不停的去查找元素,如果找到 ...

  9. 测试TwemProxy的应知应会

    一.背景 最近中间件开发组对twemproxy的发现注册机制做了改造,之前没有接触过twemproxy,借这次测试的机会,初步学习了一下twemproxy相关的知识:下面用"测试语言&quo ...

  10. day81:luffy:课程分类页面&课程信息页面&指定分类显示课程信息&分页显示课程信息

    目录 1.构建课程前端初始页面 2.course后端的准备工作 3.后端实现课程分类列表接口 4.前端发送请求-获取课程分类信息 5.后端实现课程列表信息的接口 6.前端显示列表课程信息 7.按照指定 ...