分布式计算模式:MapReduce

分布式计算模式:MapReduce分布式计算模式 MapReduce 前言什么是分而治之 分治法的原理抽象模型 MapReduce 工作原理 MapReduce 实践应用知识扩展 Fork Join 计算模式是什么意思呢 总结前言两层调度时提到 Mesos 的第二层调度是由 Framework 完成的 这里的 Framework 通常就是计算框架 比如 Hadoop Spark 等 用户基于这些计算框架 可以完成不同类型和规模的计算 Hadoop 这个框架主要用于解决海量数据的计算问题 海量数据分成多个进程 每个进程计算一部分 然后汇总


前言

两层调度时提到,Mesos 的第二层调度是由 Framework 完成的。这里的 Framework 通常就是计算框架,比如 Hadoop、Spark 等。用户基于这些计算框架,可以完成不同类型和规模的计算。

Hadoop 这个框架主要用于解决海量数据的计算问题。海量数据分成多个进程,每个进程计算一部分,然后汇总一下结果,就可以提升运算速度了。在分布式领域中就叫作 MR 模式,即 Map Reduce 模式。

什么是分而治之?

分而治之(Divide-and-Conquer),是计算机处理问题的一个很重要的思想,简称为分治法。

分治法是将一个复杂的、难以直接解决的大问题,分割成一些规模较小的、可以比较简单的或直接求解的子问题,这些子问题之间相互独立且与原问题形式相同,递归地求解这些子问题,然后将子问题的解合并得到原问题的解。

比如,现在要统计全中国的人口数,由于中国的人口规模很大,如果让工作人员依次统计每个省市的人口数,工作量会非常大。在实际统计中,通常会按照省分别统计,比如湖南省的工作人员统计湖南省的人口数,湖北省的工作人员统计湖北省的人口数等,然后汇总各个省的人口数,即可得到全国人口数。

这种分治的思想还广泛应用于计算机科学的各个领域中,分布式领域中的很多场景和问题也非常适合采用这种思想解决,并为此设计出了很多计算框架。比如,Hadoop 中的 MapReduce。

适合分治法的问题的特征:

  • 问题规模比较大或复杂,且问题可以分解为几个规模较小的、简单的同类型问题进行求解;
  • 子问题之间相互独立,不包含公共子问题;
  • 子问题的解可以合并得到原问题的解。

根据这些特征可以想到,诸如电商统计全国商品数量时,按区域或省市进行统计,然 后将统计结果合并得到最终结果等大数据处理场景,均可以采用分治法。

根据这些特征可以推导出,采用分治法解决问题的核心步骤是:

  1. 分解原问题。将原问题分解为若干个规模较小,相互独立,且与原问题形式相同的子问题。
  2. 求解子问题。若子问题规模较小且容易被解决则直接求解,否则递归地求解各个子问题。
  3. 合并解,就是将各个子问题的解合并为原问题的解。

分治法的原理

分布式原本就是为处理大规模应用而生的,所以基于分布式系统,如何分而治之地处理海量数据就是分布式领域中的一个核心问题。

Google 提出的 MapReduce 分布式计算模型(Hadoop MapReduce 是 Google 的开源实现),作为分治法的典型代表,最开始用于搜索领域,后来被广泛用于解决各种海量数据的计算问题。

抽象模型

如下图所示,MapReduce 分为 Map 和 Reduce 两个核心阶段,其中 Map 对应“分”, 即把复杂的任务分解为若干个“简单的任务”执行;Reduce 对应着“合”,即对 Map 阶段的结果进行汇总。

在这里插入图片描述

Map 阶段,将大数据计算任务拆分为多个子任务,拆分后的子任务通常具有如下特征:

  • 相对于原始任务来说,划分后的子任务与原任务是同质的,比如原任务是统计全国人口数,拆分为统计省的人口数子任务时,都是统计人口数;并且子任务的数据规模和计算规模会小很多。
  • 多个子任务之间没有依赖,可以独立运行、并行计算,比如按照省统计人口数,统计河北省的人口数和统计湖南省的人口数之间没有依赖关系,可以独立、并行的统计。

Reduce 阶段,拆分的子任务计算完成后,汇总所有子任务的计算结果,以得到最终结果。也就是汇总各个省统计的人口数,得到全国的总人口数。

MapReduce 工作原理

MapReduce 的组件结构:

在这里插入图片描述

MapReduce 主要包括以下三种组件:

  • Master,也就是 MRAppMaster,该模块像一个大总管一样,独掌大权,负责分配任务,协调任务的运行,并为 Mapper 分配 map() 函数操作、为 Reducer 分配 reduce() 函数操作。
  • Mapper worker,负责 Map 函数功能,负责执行子任务。
  • Reducer worker,负责 Reduce 函数功能,负责汇总各个子任务的结果。

基于这三种组件,MapReduce 的工作流程如下所示:

在这里插入图片描述

程序从 User Program 开始进入 MapReduce 操作流程。其中图中的“step1,step2, …,step6”表示操作步骤。

  • step1:User Program 将任务下发到 MRAppMaster 中。然后 MRAppMaster 执行任务拆分步骤,把 User Program 下发的任务划分成 M 个子任务(M 是用户自定义的数值)。假设 MapReduce 函数将任务划分成了 5 个,其中 Map 作业有 3 个,Reduce 作业有 2 个;集群内的 MRAppMaster 以及 Worker 节点都有任务的副本。
  • step2:MRAppMaster 分别为 Mapper 和 Reducer 分配相应的 Map 和 Reduce 作业。 Map 作业的数量就是划分后的子任务数量,也就是 3 个;Reduce 作业是 2 个。
  • step3:被分配了 Map 作业的 Worker,开始读取子任务的输入数据,并从输入数据中抽取出

    键值对,每一个键值对都作为参数传递给 map() 函数。
  • step4:map() 函数的输出结果存储在环形缓冲区 kvBuffer 中,这些 Map 结果会被定期写入本地磁盘中,被存储在 R 个不同的磁盘区。R 表示 Reduce 作业的数量,也是由用户定义的。在这个案例中,R=2。此外每个 Map 结果的存储位置都会上报给 MRAppMaster。
  • step5:MRAppMaster 通知 Reducer 它负责的作业在哪一个分区,Reducer 远程读取相应的 Map 结果,即中间键值对。当 Reducer 把它负责的所有中间键值对都读过来后,首先根据键值对的 key 值对中间键值对进行排序,将相同 key 值的键值对聚集在一起,从而有利于 Reducer 对 Map 结果进行统计。
  • step6:Reducer 遍历排序后的中间键值对,将具有相同 key 值的键值对合并,并将统计结果作为输出文件存入负责的分区中。

从上述流程可以看出,整个 MapReduce 的工作流程主要可以概括为 5 个阶段: Input(输入)、Splitting(拆分)、Mapping(映射)、Reducing(化简)以及 Final Result(输出)。

所有 MapReduce 操作执行完毕后,MRAppMaster 将 R 个分区的输出文件结果返回给 User Program,用户可以根据实际需要进行操作。比如,通常并不需要合并这 R 个输出文件,而是将其作为输入交给另一个 MapReduce 程序处理。

MapReduce 实践应用

一个电商统计用户消费记录的例子,巩固 MapReduce 的功能。每隔一段时间,电商都会统计该时期平台的订单记录,从而分析用户的消费倾向。在不考虑国外消费记录的前提下,全国范围内的订单记录已经是一个很大规模的工程了。

电商往往会在每个省份、多个城市分布式地部署多个服务器, 用于管理某一地区的平台数据。因此针对全国范围内的消费统计,可以拆分成对多个省份的消费统计,并再一次细化到统计每一个城市的消费记录。

假设要统计苏锡常地区第二季度手机订单数量 Top3 的品牌。具体的统计步骤:

  1. 任务拆分(Splitting 阶段)。根据地理位置,分别统计苏州、无锡、常州第二季度手机订单 Top3 品牌,从而将大规模任务划分为 3 个子任务。
  2. 通过循环调用 map() 函数,统计每个品牌手机的订单数量。key 为手机品牌, value 为手机购买数量(单位:万台)。如下图 Mapping 阶段所示(为简化描述,图中直接列出了统计结果)。
  3. 与前面计算流程不同的是,Mapping 阶段和 Reducing 阶段中间多了一步 Shuffling 操作。Shuffling 阶段主要是读取 Mapping 阶段的结果,并将不同的结果划分到不同的区。在大多数参考文档中,Mapping 和 Reducing 阶段的任务分别定义为映射以及归约。但是,在映射之后,要对映射后的结果进行排序整合,然后才能执行归约操作,因此往往将这一排序整合的操作单独放出来,称之为 Shuffling 阶段。
  4. Reducing 阶段,归并同一个品牌的购买次数。
  5. 得到苏锡常地区第二季度 Top3 品牌手机的购买记录。

在这里插入图片描述

由上述流程可以看出,Map/Reduce 作业和 map()/reduce() 函数是有区别的:

  • Map 阶段由一定数量的 Map 作业组成,这些 Map 作业是并发任务,可以同时运行, 且操作重复。Map 阶段的功能主要由 map() 函数实现。每个 Map 作业处理一个子任务 (比如一个城市的手机消费统计),需要调用多次 map() 函数来处理(因为城市内不同的居民倾向于不同的手机)。
  • Reduce 阶段执行的是汇总任务结果,遍历 Map 阶段的结果从而返回一个综合结果。与 Reduce 阶段相关的是 reduce() 函数,它的输入是一个键(key)和与之对应的一组数据(values),其功能是将具有相同 key 值的数据进行合并。Reduce 作业处理一个分区的中间键值对,期间要对每个不同的 key 值调用一次 reduce() 函数。在完成 Map 作业后,每个分区中会存在多个临时文件;而执行完 Reduce 操作后,一个分区最终只有 一个输出文件。

知识扩展:Fork-Join 计算模式是什么意思呢?

MapReduce 是一种分而治之的计算模式,在分布式领域中,除了典型的 Hadoop 的 MapReduce(Google MapReduce 的开源实现),还有 Fork-Join。

Fork-Join 是 Java 等语言或库提供的原生多线程并行处理框架,采用线程级的分而治之计算模式。它充分利用多核 CPU 的优势,以递归的方式把一个任务拆分成多个“小任务”, 把多个“小任务”放到多个处理器上并行执行,即 Fork 操作。当多个“小任务”执行完成之后,再将这些执行结果合并起来即可得到原始任务的结果,即 Join 操作。

虽然 MapReduce 是进程级的分而治之计算模式,但与 Fork-Join 的核心思想是一致的。 因此 Fork-Join 又被称为 Java 版的 MapReduce 框架。

但 MapReduce 和 Fork-Join 之间有一个本质的区别:

  • Fork-Join 不能大规模扩展,只适用于在单个 Java 虚拟机上运行,多个小任务虽然运行在不同的处理器上,但可以相互通信,甚至一个线程可以“窃取”其他线程上的子任务。
  • MapReduce 可以大规模扩展,适用于大型计算机集群。通过 MapReduce 拆分后的任务,可以跨多个计算机去执行,且各个小任务之间不会相互通信。

总结

分而治之是将一个复杂的、难以直接解决的大问题,分割成一些规模较小的、可以直接求解的子问题,这些子问题互相独立且与原问题形式相同,递归地解这些子问题,然后将子问题的解合并以后就是原问题的解。

分布式计算模型 MapReduce 就运用了分而治之的思想,通过 Map 操作将大任务分成多个较小的任务去执行,得到的多个结果再通过 Reduce 操作整合成一个完整的结果。

在这里插入图片描述
分而治之的思想是简单且实用的处理复杂问题的方法。所以无论是计算机领域还是其他研究领域亦或日常生活中,都可以用分治法去处理很多复杂庞大的问题,将大问题划分成多个小问题,化繁为简、化整为零。

其实很多算法并不是凭空创造出来的,都是源于生活并服务于生活的。在日常工作学习中,对眼前的问题一筹莫展时,就可以将其化繁为简,从最简单的小问题出发,逐渐增加问题的规模,进而解决这个复杂的问题。同样也可以借鉴生活中的例子去解决专业问题。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/219014.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月17日 下午10:59
下一篇 2026年3月17日 下午10:59


相关推荐

  • 如何利用vue和php做前后端分离开发?

    如何利用vue和php做前后端分离开发?

    2021年10月11日
    70
  • Java对象的序列化(Serialization)和反序列化详解

    Java对象的序列化(Serialization)和反序列化详解1.序列化和反序列化序列化(Serialization)是将对象的状态信息转化为可以存储或者传输的形式的过程,一般将一个对象存储到一个储存媒介,例如档案或记忆体缓冲等,在网络传输过程中,可以是字节或者XML等格式;而字节或者XML格式的可以还原成完全相等的对象,这个相反的过程又称为反序列化;2.Java对象的序列化和反序列化在Java中,我们可以通过多种方式来创建对象,并且只要对象…

    2022年6月16日
    29
  • Mac anaconda 安装openCV

    Mac anaconda 安装openCVMacanaconda 安装 openCV1 首先去清华镜像源网站下载对应版本的 opencv 我下载的是 opencv python 4 5 2 54 cp38 cp38 macosx 10 15 x86 64 whl 下载网址 https pypi tuna tsinghua edu cn simple opencv python 2 在 anaconda 中打开终端 cd 到 whl 的下载地址的文件夹 我下载的 whl 文件的放在 downloads 文件夹下 则终端输入 cddownloads3 输入 p

    2026年3月26日
    2
  • t-io文档_如何区别服务端与客户端

    t-io文档_如何区别服务端与客户端<dependency><groupId>org.t-io</groupId><artifactId>tio-core</artifactId><version>3.7.4.v20210808-RELEASE</version></dependency>总共五个类。数据模型Packet、客户端处理器、客户端监听器.

    2022年10月2日
    3
  • mysql explain 无效[通俗易懂]

    mysql explain 无效[通俗易懂]最近分析一段sql是不是命中索引的,发现有的时候explain是可以的,有的时候又不行显然我们是要下面的结果。经过分析,原来是中间件的原因,直连mysql的可以用explain连mycat就不行。解决办法可以使用desc,也能达到同样效果…

    2022年10月17日
    4
  • 一篇文章带你深入理解 Java 中的Class.getClassLoader[通俗易懂]

    一篇文章带你深入理解 Java 中的Class.getClassLoader[通俗易懂]文章目录一、ClassLoader的作用二、ClassLoader层次结构三、Class加载时调用类加载器的顺序一、ClassLoader的作用我们都知道java程序写好以后是以.java(文本文件)的文件存在磁盘上,然后,我们通过(bin/javac.exe)编译命令把.java文件编译成.class文件(字节码文件),并存在磁盘上。但是程序要运行,首先一定要把.class文件加载…

    2022年4月29日
    49

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号