【Hadoop】MapReduce原理剖析(Map,Shuffle,Reduce三阶段)

news2025/1/15 16:43:33

文章目录

  • 1. Map阶段
    • 1.1 把输入文件(夹)划分为很多InputSplit(Split)
    • 1.2 分配并执行map作业
  • 2. Shuffle阶段
    • 2.1 Partition(分区)
    • 2.2 Sort(排序)
    • 2.3 Group(分组)
    • 2.4 Combiner(规约)
    • 2.5 序列化并写入Linux磁盘内存
    • 2.6 反序列化读取数据到不同的reduce节点
    • 2.7 Reduce端数据进行合并、排序、分组
  • 3. Reduce阶段
    • 3.1 执行reduce方法
    • 3.2 保存结果到HDFS

       MapReduce是一种分布式计算模型,是Google提出来的,主要用于搜索领域,解决海量数据的计算问题。我自己在学习的过程中遇到了很多疑问,例如:

  • 为什么有的人博客中写:“Block默认大小为64M”,而我学的Block默认却是128M?
  • Split的大小划分与Block有什么关系?
  • Partition分区有什么用?为什么要分区?是如何进行分区的?
  • Shuffle到底包含那些过程?是只包含从Map到Reduce的传输么?
  • MapReduce到底有几个阶段?怎么每一篇博客的阶段划分都不一样?

       MapReduce的全套过程分为三个大阶段,分别是Map、Shuffle和Reduce。结合多篇资料,我最终确定划分11个小步骤来描述这个过程,在后续的内容中我也会结合一部分源码来进行剖析。
在这里插入图片描述

1. Map阶段

map就是对数据进行局部汇总,reduce就是对局部数据进行最终汇总。

1.1 把输入文件(夹)划分为很多InputSplit(Split)

       首先,一个Block的默认大小为128M,之所以会有博客写为64M,是因为在Hadoop2.x中修改了这个默认设置。Split的默认大小为128M,但并不是每一个Split都是128M,具体分析过程如下,请看如下源码:

SplitSize = Math.max(minSize, Math.min(maxSize, BlockSize));

       也就是说Split的默认大小取决于minSize、maxSize以及BlockSize这三个变量。
       其中minSize的相关源码为:Math.max(getFormatMinSplitSize(), getMinSplitSize(job));这行源码中getFormatMinSplitSize()的值为1,getMinSplitSize(job)的值为0,因此minSize的值为1;
       maxSize的相关源码为:maxSize=getMaxSplitSize(job)=Long.MAX_VALUE,也就是说maxSize的值为Long.MAX_VALUE;
       BlockSize的值默认为128M。
       所以最终SplitSize=128M。

       上面说的是Split的默认大小与Block相同,都是128M,但并不是说一个Block就对应一个Split,这里仅描述大小关系。但是之所以说并不是每一个Split都是128M,因为文件总不可能都是128M的整数倍,那么多出的那一部分怎么处理?源码中会判断剩余待切分文件大小/splitsize是否大于SPLIT_SLOP(值为1.1),如果大于1.1,那么会继续切分;如果小于1.1,会将剩下的部分切到同一个Split。

举几个例子帮助理解:

  1. 一个1G的文件,会产生多少个Split?
    Block块默认是128M,所以1G的文件会产生8个Block块,默认情况下Split的大小和Block块的大小一致,也就是8个Split。
  2. 1000个文件,每个文件100KB,会产生多少个Split?
    一个文件,不管再小,都会占用一个Block,所以这1000个小文件会产生1000个Block,默认情况下Split的大小和Block块的大小一致,那最终会产生1000个Split。
  3. 一个140M的文件,会产生多少个Split?
    这个有点特殊,140M的文件虽然会产生2个Block,但140M/128M=1.09375<1.1,所以这个文件只会产生一个Split,这个文件其实再稍微大1M就可以产生2个Split。

1.2 分配并执行map作业

       默认一个Split对应一个Map,框架调用Mapper类中的map(…)函数,map函数的输入是<k1,v1>,输出是<k2,v2>。

2. Shuffle阶段

在这里插入图片描述

       Shuffle是介于Map和Reduce之间的一个过程,可以分为Map端的shuffle和Reduce端的Shuffle。MapReduce中,Map阶段处理的数据如何传递给Reduce阶段,是框架中最关键的一个流程,这个流程就叫Shuffle。

2.1 Partition(分区)

       分区默认使用HashPartitioner,使用哈希方法对key进行分区,getPatition方法相关源码为:(key.hashcode()&Inyeger.MAX_VALUE)%numReduceTask,其中numReduceTask默认为1,而任何书向1取余都为0,因此默认只有一个分区,又因为一个分区对应一个Reduce任务,所以只有也一个Ruduce。若要提高并行度,增加Reduce任务数,只需要修改numReduceTask数值即可。
       但是使用这种哈希方法分区有可能会导致数据倾斜问题,就比如现在一个文件中包含100万条数据,每个数据都是一个十以内数字,其中数字5出现了900万次,现在设置numReduceTask为10,那么根据哈希方法分区,其中的900万条数据都被分到分区5对应的Reduce任务下,这无疑是严重的影响了系统的运行效率。这种问题的解法并不会在这里展开说明,后续博客中会更新相关内容。

2.2 Sort(排序)

       按照Key,采用字典顺序进行排序,Sort操作无论是否需要,在逻辑上都必须执行。

2.3 Group(分组)

       分组是根据map<key, value>中的key进行分组,目的是提高Reduce的并行度。

2.4 Combiner(规约)

       规约是可选操作,在map端输出中先做一次合并,相当于做了一个局部的reduce操作。规约操作会将map输出的<k1,v1>,<k1,v2>,<k2,v3>这样的数据转化为<k1,{v1,v2}>,<k2,{v3}>。

2.5 序列化并写入Linux磁盘内存

       序列化(Serialization)是指把结构化对象转化为字节流,当要在进程间传递对象或持久化对象的时候,就需要进行这个操作。这里进行序列化是为了把map的执行结果写入内存。

2.6 反序列化读取数据到不同的reduce节点

       反序列化(Deserialization)是序列化的逆过程,把字节流转为结构化对象,当要将接收到或从磁盘读取的字节流转换为对象,就要进行这个操作。这里进行反序列化是为了读取数据到不同的reduce节点。

2.7 Reduce端数据进行合并、排序、分组

       reduce端接收到的是多个map的输出,对多个map任务中相同分区的数据进行合并、排序、分组。虽然之前在map中已经做了排序和分组,这边也做这些操作其实并不重复,因为map端是局部的操作,而reduce端是全局的操作,之前是每个map任务内进行排序,是有序的,但是多个map任务之间就是无序的了。

3. Reduce阶段

3.1 执行reduce方法

       框架调用Reducer类中的reduce方法,reduce方法的输入是<k2,{v2}>,输出是<k3,v3>。一个<k2,{v2}>调用一次reduce函数。程序员需要覆盖reduce函数,实现具体的业务逻辑。

3.2 保存结果到HDFS

       框架会把reduce的输出结果保存到HDFS中。

       以上就是博客的全部内容,MapReduce的相关操作其实并不繁琐,至少逻辑顺序是非常清晰明了的,希望大家都能有所收获。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/178640.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【数据库概论】第五章 数据库完整性

第五章 数据库完整性 目录第五章 数据库完整性5.1 实体完整性5.2 参照实体性5.3 用户定义的完整性1.属性上的约束条件2.元组上的约束条件5.4 完整性约束命名子句5.5 域中的完整性限制5.6 断言5.7 触发器(Trigger)一、定义触发器二、激活触发器三、删除触发器数据库的完整性指的…

好客租房-13.WebMagic

13. 项目接入ES编写爬虫抓取房源数据开发搜索房源接口服务整合前端开发实现搜索功能优化搜索功能增加高亮和分页功能热词推荐功能实现拼音分词13.1 制作假数据13.1.1 WebMagic抓取数据为了丰富我们的房源数据&#xff0c;所以我们采用WebMagic来抓取一些数据&#xff0c;目标网…

还在纠结选择用什么浏览器?手机端用国产浏览器也很香

一说到受欢迎的电脑浏览器&#xff0c;大家肯定不约而同地说谷歌浏览器。微软edge浏览器能够同步书签、插件也非常多&#xff0c;因为这些优势深受国人的喜爱。有人纠结在国内选择谷歌好&#xff0c;还是edge浏览器好呢&#xff1f;可能有的人哪个也不选&#xff0c;反而在电脑…

Docker 解决 `denied: requested access to the resource is denied`

背景 由于不可描述的原因&#xff0c;相对于以前&#xff0c;最近在更加频繁的迁移服务器&#xff0c;简单的 Shell 脚本已经不能满足需求了&#xff0c;于是将所有的项目 Docker 化。 部分不含敏感配置的项目准备放到 DockerHub 上面&#xff0c;但是在 docker push 的时候报…

利用 Algolia 为静态博客搭建实现内容搜索

现在静态博客的标配之一就是博客搜索&#x1f50d;&#xff0c;我也是通过搭建博客发现了它&#xff0c;这篇主要记录一下怎么使用 algolia 完成博客搜索&#xff0c;自己的博客搭建使用的是 docusaurus 。 注册账号 首先需要去 algolia 官网注册自己的账号&#xff0c;可以直…

Java线程池(超详细)

1、基本概念 Java线程需要经过线程的创建&#xff0c;调用和销毁整个过程&#xff0c;频繁的创建和销毁会大大影响性能&#xff0c;所以引入的线程池&#xff1a; 好处&#xff1a; 提升性能&#xff1a;线程池能独立负责线程的创建、维护和分配线程管理&#xff1a;每个Java…

k8s安装kuboard面板

前面介绍了k8s的dashboard面板&#xff0c;这里介绍国人开发的kuboard面板&#xff0c;相较于dashboard面板&#xff0c;kuboard面板对很多运维调试功能做了很多增强。官方文档&#xff1a;https://www.kuboard.cn/install/v3/install.html#kuboard-v3-x-%E7%89%88%E6%9C%AC%E8…

实现一个TCP客户端——服务端协议

目录 TCP客户端常见的API&#xff1a; ServerSocket: Socket&#xff1a; TCP服务端(单线程版本) 属性构造方法: 启动服务端的start()方法 步骤一&#xff1a;接收客户端发送的socket 步骤二&#xff1a; 调用processConnection方法来处理客户端发送的连接 ①通过参数传入的…

影像组学|特征定义以及提取

一、 影像组学特征分类 1.1 影像组学特征分类 1.1.1 一阶统计特征 一阶统计特征&#xff0c;反应所测体素的对称性、均匀性以及局部强度分布变化。包括中值&#xff0c;平均值&#xff0c;最小值&#xff0c;最大值&#xff0c;标准差&#xff0c;偏度&#xff0c;峰度等。 …

【Linux】六、Linux 基础IO(三)|文件系统|软硬链接|文件的三个时间

目录 八、文件系统 8.1 磁盘 8.1.1 磁盘的物理结构 8.1.2 磁盘的存储结构 8.1.3 磁盘的逻辑结构 8.2 inode 九、软硬链接 9.1 软链接 9.2 硬链接 9.3 当前路径(.)和上级路径(..) 十、文件的三个时间 八、文件系统 上面的内容谈论的都是一个被打开文件&#xff0c;那…

如何将两个录音合成一个?这篇文章告诉你

现如今&#xff0c;很多小伙伴都加入到短视频行业当中。而短视频的制作往往需要将多段音频进行一个合并。那么问题来了&#xff0c;当你想多个音频进行合并在一起的时候&#xff0c;你是怎么做的呢&#xff1f;其实很简单&#xff0c;我们只需要借助市面上的一些合并软件就好了…

初始网络

文章目录初始网络局域网 / 广域网IP地址 和 端口号认识协议协议分层初始网络 这里可以先自行在网上了解一下网络的发展史 也就是互联网是怎么来的. 局域网 / 广域网 关于网络的发展史 , 会涉及到两个非常重要的术语 &#xff0c;也就是 局域网&#xff0c;和广域网 。 局域网 &…

JavaEE多线程-阻塞队列

目录一、认识阻塞队列1.1 什么是阻塞队列&#xff1f;1.2 生产者消费者模型1.3 标准库中的阻塞队列类二、循环队列实现简单阻塞队列2.1 实现循环队列2.2 阻塞队列实现一、认识阻塞队列 1.1 什么是阻塞队列&#xff1f; 阻塞队列&#xff1a;从名字可以看出&#xff0c;他也是…

简明Java讲义 2:数据类型和运算符

目录 1、安装IDE编辑器 2、关键字和保留字 3、标识符 4、分隔符 5、数据类型 6、基本类型的数据类型转换 7、表达式类型的自动提升 8、变量 9、运算符 10、运算符的优先级 1、安装IDE编辑器 在开始内容之前&#xff0c;先下载IDE&#xff0c;可以是Eclipse或STS&…

Python函数(函数定义、函数调用)用法详解

Python 中函数的应用非常广泛&#xff0c;前面章节中我们已经接触过多个函数&#xff0c;比如 input() 、print()、range()、len() 函数等等&#xff0c;这些都是 Python 的内置函数&#xff0c;可以直接使用。除了可以直接使用的内置函数外&#xff0c;Python 还支持自定义函数…

LeetCode刷题模版:201 - 210

目录 简介201. 数字范围按位与202. 快乐数203. 移除链表元素204. 计数质数205. 同构字符串206. 反转链表207. 课程表【未实现】208. 实现 Trie (前缀树)209. 长度最小的子数组210. 课程表 II【未实现】结语简介 Hello! 非常感谢您阅读海轰的文章,倘若文中有错误的地方,欢迎您…

LeetCode[1319]连通网络的操作次数

难度&#xff1a;中等题目&#xff1a;用以太网线缆将 n台计算机连接成一个网络&#xff0c;计算机的编号从 0到 n-1。线缆用 connections表示&#xff0c;其中 connections[i] [a, b]连接了计算机 a和 b。网络中的任何一台计算机都可以通过网络直接或者间接访问同一个网络中其…

(十六)异步编程

CompletableFuture在Java8中推出&#xff0c;Java8中的异步编程就是依靠此类。几种任务接口四种任务无参数有一个参数有两个参数无返回值RunnableConsumerBiConsumer有返回值SupplierFunctionBiFunctionCompletionStage接口这个类中定义的许多能够链式调用的方法和组合方法时是…

Unity3DVR开发—— XRInteractionToolkit(PicoNeo3)

目录 一、开发前的准备 二、基础配置 三、Pico项目配置 四、添加基础功能 一、开发前的准备 1、为了方便开发&#xff0c;先在Pico开发者平台里下载预览工具 Pico开发者平台https://developer-global.pico-interactive.com/sdk?deviceId1&platformId1&itemId17 2、…

【哈希表】关于哈希表,你该了解这些!

【哈希表】理论基础1 哈希表2 哈希函数3 哈希碰撞3.1 拉链法3.2 线性探测法4 常见的三种哈希结构5 总结1 哈希表 哈希表 Hash table &#xff08;一些书籍翻译为散列表&#xff09; 哈希表是根据关键码的值而直接进行访问的数据结构。 直白来讲其实数组就是一张哈希表。 哈希表…