浅谈MapReduce核心之shuffle

2024-09-06 05:48

本文主要是介绍浅谈MapReduce核心之shuffle,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Hadoop拥有三大核心组件,HDFS作为底层的分布式文件系统,MapReduce作为计算框架,yarn作为资源调度管理器。

对于开发人员来说,理解MapReduce是很重要的。

在WordCount程序中,map生成的结果是一个个的元组,类似于(hello,1),非常非常多的元组,由context写入到hdfs中,而后续的Reduce阶段,实际上reduce方法接收的参数类似于这种,(hello,<1,2,3,4,5>);这里面,问题就出现了,为什么map的输出结果,到了reduce端成了这个样子,其中最为关键的就是称为shuffle的阶段。

本文,就对shuffle阶段做一定的介绍。


上图,是诸多介绍shuffle过程用得比较多的一张图。

实际上,我们的实现知识map的逻辑以及reduce的逻辑,而以上很多的逻辑,隐藏在MapReduce的内核,只有深刻理解其内部原理,才能写出更好的MapReduce程序,譬如可以很好地避免数据倾斜问题。

以下介绍,全部基于WordCount。

1:数据读取阶段

代码中,最基本的读取应该是InputFormat,其本身是个抽象类,具有很多实现,可以从数据库,本地文件或者HDFS等很多地方读取数据,对于wordCount来说,使用的是FileInputFormat,其会读取文件,并且按照HDFS的存储格式,将文件存储起来,这样就会将文件进行切片,生成一个一个小的split,切分的标准应该是依据于block的大小;而读入的效果,则是类似于这种<offset,line>,offset指的是每一行的偏移量,而line则是每一行的内容,这就是接下来Map阶段的输入。

2:map阶段

map阶段,就是我们通常使用的逻辑,当然,执行起来肯定不单单一个map,而是有很多map在众多节点上分布执行,这里面map基本上都会本地化读取,就是尽可能地读取本机的数据来进行map的处理;而对于处理的结果,会先写到内存中;就单说一个map吧,会源源不断地把结果写入到内存中,但是,这块内存区的大小是有限制的,不可能一直写,通常在其内存区写入达到80%的时候,map输出的结果,就会往磁盘内spill数据。

3:spill阶段

这部分,就是map生成的结果不断往磁盘内写数据的过程,而实际上,spill过程中,会按照partition的不同,分成不同的区,而在区内,数据是有序的;这里提到的区,数量与后面的reducetask的数量是一致的,方便reducetask拉取数据,简单说,就是分区有序,排序算法用的是快速排序;其实我觉得,在内存中排序其实更快一些,没看源码,具体逻辑不清楚了,总之,每次spill都会生成多个对应于多个partition的有序数据;而随着map执行完毕,通常会有partitionNum * spillTimes的文件;而且,每个map任务都有数据。

4:merge

其实,在Map端,应该也是有数据的merge,不仅仅是最后reduce拉取数据之前的combine使用;在这里,对于每个partition来说,都有很多的spill小文件,所以会把这些小文件汇聚成大文件,当然,这里也是排序的,采用归并排序的算法;最后,对于一个map任务来说,其管辖下的众多partition,各自会有自己的大文件,这里,就是reduce处理的Iterator的一小部分了;另外,这里必须要提一下combine,其内部实现逻辑基本与reduce一致,会把数据进行合并,目的就是减小拉取到reduce阶段的数据,比如说如果是max操作或者min操作,可以很大程度减小发送给reducer需要拉取的结果了。

这里,reducer也是优先处理本地的map生成的数据,但通常都要拉取很多文件,因为有些时候最终的reducer只有一个;这里,还要插播一句,map文件存储到本地会有一定的压缩策略,这也是减小reducer拉取数据的一个办法;综上,map端会对数据进行压缩,执行简单的combine逻辑,进行spill文件的合并,准备好reducer拉取的文件。

5:copy

这就是拉取的逻辑了,每个reducer都会从其他的mapper拉取数据,而且这里还存在一个mapReduce的瓶颈,那就是必须所有的map全部结束之后,reducer才能开始拉取数据;一般来说,reducer拉取到的数据,来自于多个mapper。

6:sort & merge

数据拉取过来之后,还需要进行排序:原因在于,虽然拉取到的数据属于一定的范围,但是直接组合在一起并不一定是有序的,所以还需要一定的排序操作;这里边的merge,指的是reducer端的merge,生成最终用于Reducer处理的数据;而reducer对于这些文件进行处理,生成最终的结果。

其实大家计算的过程中会看到,最终有多少个reducer,对应多少个分区,最后就会生成几个文件的。

shuffle原理大致如上。

其实MapReduce是存在几个瓶颈的:

  1. map结果写入磁盘:写入磁盘之后,后期还需要再进行读取出来,进行传输,这个性能其实是比较差的。注解:网上很多地方提到这一点,但是我觉得,如果不落盘的话,那怎么传输给reducer?内存传输?没搞懂大家为啥都一致认为这一点是spark要优于MR的地方,都是说spark内存运算。
  2. 当所有的mapper都结束之后,才能开始reducer的操作,这样导致有些执行比较快的mapper,只能空等,而如果让先完成的mapper可以直接把数据发送给reducer的话,对于性能有一定提升。

参考资料:

  1. http://blog.csdn.net/aijiudu/article/details/72353510
  2. http://blog.csdn.net/techchan/article/details/53405519

这篇关于浅谈MapReduce核心之shuffle的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1141175

相关文章

Spring Boot 中 RestTemplate 的核心用法指南

《SpringBoot中RestTemplate的核心用法指南》本文详细介绍了RestTemplate的使用,包括基础用法、进阶配置技巧、实战案例以及最佳实践建议,通过一个腾讯地图路线规划的案... 目录一、环境准备二、基础用法全解析1. GET 请求的三种姿势2. POST 请求深度实践三、进阶配置技巧1

Java中的CompletableFuture核心用法和常见场景

《Java中的CompletableFuture核心用法和常见场景》CompletableFuture是Java8引入的强大的异步编程工具,支持链式异步编程、组合、异常处理和回调,介绍其核心用法,通过... 目录1、引言2. 基本概念3. 创建 CompletableFuture3.1. 手动创建3.2.

Java线程池核心参数原理及使用指南

《Java线程池核心参数原理及使用指南》本文详细介绍了Java线程池的基本概念、核心类、核心参数、工作原理、常见类型以及最佳实践,通过理解每个参数的含义和工作原理,可以更好地配置线程池,提高系统性能,... 目录一、线程池概述1.1 什么是线程池1.2 线程池的优势二、线程池核心类三、ThreadPoolE

MySQL快速复制一张表的四种核心方法(包括表结构和数据)

《MySQL快速复制一张表的四种核心方法(包括表结构和数据)》本文详细介绍了四种复制MySQL表(结构+数据)的方法,并对每种方法进行了对比分析,适用于不同场景和数据量的复制需求,特别是针对超大表(1... 目录一、mysql 复制表(结构+数据)的 4 种核心方法(面试结构化回答)方法 1:CREATE

Spring Boot 集成 mybatis核心机制

《SpringBoot集成mybatis核心机制》这篇文章给大家介绍SpringBoot集成mybatis核心机制,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值... 目录Spring Boot浅析1.依赖管理(Starter POMs)2.自动配置(AutoConfigu

Spring IOC核心原理详解与运用实战教程

《SpringIOC核心原理详解与运用实战教程》本文详细解析了SpringIOC容器的核心原理,包括BeanFactory体系、依赖注入机制、循环依赖解决和三级缓存机制,同时,介绍了SpringBo... 目录1. Spring IOC核心原理深度解析1.1 BeanFactory体系与内部结构1.1.1

Spring Boot/Spring MVC核心注解的作用详解

《SpringBoot/SpringMVC核心注解的作用详解》本文详细介绍了SpringBoot和SpringMVC中最常用的15个核心注解,涵盖了请求路由映射、参数绑定、RESTfulAPI、... 目录一、Spring/Spring MVC注解的核心作用二、请求映射与RESTful API注解系列2.1

Python异常处理之避免try-except滥用的3个核心原则

《Python异常处理之避免try-except滥用的3个核心原则》在Python开发中,异常处理是保证程序健壮性的关键机制,本文结合真实案例与Python核心机制,提炼出避免异常滥用的三大原则,有需... 目录一、精准打击:只捕获可预见的异常类型1.1 通用异常捕获的陷阱1.2 精准捕获的实践方案1.3

深入浅出Java中的Happens-Before核心规则

《深入浅出Java中的Happens-Before核心规则》本文解析Java内存模型中的Happens-Before原则,解释其定义、核心规则及实际应用,帮助理解多线程可见性与有序性问题,掌握并发编程... 目录前言一、Happens-Before是什么?为什么需要它?1.1 从一个问题说起1.2 Haht

Python进阶之列表推导式的10个核心技巧

《Python进阶之列表推导式的10个核心技巧》在Python编程中,列表推导式(ListComprehension)是提升代码效率的瑞士军刀,本文将通过真实场景案例,揭示列表推导式的进阶用法,希望对... 目录一、基础语法重构:理解推导式的底层逻辑二、嵌套循环:破解多维数据处理难题三、条件表达式:实现分支