文章目录

大数据计算的核心思路是移动计算比移动数据更划算

​MapReduce​​ 既是一个编程模型,又是一个计算框架

开发人员必须基于 MapReduce 编程模型进行编程开发,然后将程序通过 MapReduce 计算框架分发到 Hadoop 集群中运行

​MapReduce​​​ 可进行关系代数运算(​​SQL​​计算),矩阵运算(图计算)等。


一、编程模型


编程模型只包含 ​​Map​​​ 和 ​​Reduce​​ 两个过程

  1. ​Map​​​ 的主要输入是一对​​<key, value>​​​ 值,经过​​Map​​​ 计算后输出一对​​<key, value>​​​ 值;然后将相同​​key​​​ 合并,形成​​List<key, value>​
  2. 再将这个​​List<key, value>​​​ 输入​​Reduce​​​,经过计算输出零个或多个​​<key, value>​​ 对

以 ​​WordCount​​ 举个栗子



​WordCount​​ 计算过程

需求:统计文本中词频(每个单词出现的次数)

这个文本很大,大到无法全部加载进内存

首先,文本被切割并存储,例如切割成块并存储在 ​​HDFS​

计算过程如图:

【MapReduce】之 工作原理_mapreduce




二、计算框架


问题

  1. 上个​​WordCount​​ 程序如何在分布式集群中运行起来?
  2. ​MapReduce​​ 程序又如何找到相应的数据并进行计算?

这两个问题可扩展为:

  • 如何为每个数据块分配一个​​Map​​ 计算任务,也就是代码是如何发送到数据块所在服务器的,发送后是如何启动的,启动以后如何知道自己需要计算的数据在文件什么位置(​​BlockID​​ 是什么)。
  • 处于不同服务器的​​Map​​ 输出的 ,如何把相同的 ​​Key​​ 聚合在一起发送给 ​​Reduce​​ 任务进行处理。

这两个问题分别如下图红圈:

【MapReduce】之 工作原理_数据_02



(1)​​MR​​作业启动

主要包括:​​Map​​​过程 和 ​​Reduce​​过程

​MapReduce​​运行过程涉及三类关键进程:

  1. 大数据应用进程。

这类进程是启动 ​​MapReduce​​​ 程序的主入口,主要是指定 ​​Map​​​ 和 ​​Reduce​​​ 类、输入输出文件路径等,并提交作业给 ​​Hadoop​​​ 集群,​​JobTracker​​​ 进程。这是由用户启动的 ​​MapReduce​​​ 程序进程,比如 ​​WordCount​​ 程序。

  1. ​JobTracker​​ 进程。

这类进程根据要处理的输入数据量,命令下面提到的 ​​TaskTracker​​​ 进程启动相应数量的 ​​Map​​​ 和 ​​Reduce​​​ 进程任务,并管理整个作业生命周期的任务调度和监控。这是 Hadoop 集群的常驻进程,需要注意的是,​​JobTracker​​​ 进程在整个 ​​Hadoop​​ 集群全局唯一。

  1. ​TaskTracker​​ 进程。

这个进程负责启动和管理 ​​Map​​​ 进程以及 ​​Reduce​​​ 进程。因为需要每个数据块都有对应的 ​​map​​​ 函数,​​TaskTracker​​​ 进程通常和 ​​HDFS​​​ 的 ​​DataNode​​​ 进程启动在同一个服务器。也就是说,​​Hadoop​​​ 集群中绝大多数服务器同时运行 ​​DataNode​​​ 进程和 ​​TaskTracker​​ 进程。

整理流程入下图:

  1. 应用进程​​JobClient​​ 将用户作业 ​​JAR​​ 包存储在 ​​HDFS​​ 中,将来这些 ​​JAR​​ 包会分发给 ​​Hadoop​​ 集群中的服务器执行 ​​MapReduce​​ 计算。
  2. 应用程序提交​​job​​ 作业给 ​​JobTracker​​。

3.​​JobTracker​​​ 根据作业调度策略创建 ​​JobInProcess​​​ 树,每个作业都会有一个自己的 ​​JobInProcess​​ 树。

4.​​JobInProcess​​​ 根据输入数据分片数目(通常情况就是数据块的数目)和设置的 ​​Reduce​​​ 数目创建相应数量的 ​​TaskInProcess​​。

5.​​TaskTracker​​​ 进程和 ​​JobTracker​​ 进程进行定时通信。

  1. 如果​​TaskTracker​​​ 有空闲的计算资源(有空闲 CPU 核心),​​JobTracker​​​ 就会给它分配任务。分配任务的时候会根据​​TaskTracker​​ 的服务器名字匹配在同一台机器上的数据块计算任务给它,使启动的计算任务正好处理本机上的数据,以实现“移动计算比移动数据更划算”。

7.​​TaskTracker​​​ 收到任务后根据任务类型(是 ​​Map​​​ 还是 ​​Reduce​​​)和任务参数(作业 ​​JAR​​​ 包路径、输入数据文件路径、要处理的数据在文件中的起始位置和偏移量、数据块多个备份的 ​​DataNode​​​ 主机名等),启动相应的 ​​Map​​​ 或者 ​​Reduce​​ 进程。

8.​​Map​​​ 或者 ​​Reduce​​​ 进程启动后,检查本地是否有要执行任务的 ​​JAR​​​ 包文件,如果没有,就去 ​​HDFS​​​ 上下载,然后加载 ​​Map​​​ 或者 ​​Reduce​​ 代码开始执行。

  1. 如果是​​Map​​​ 进程,从​​HDFS​​​ 读取数据(通常要读取的数据块正好存储在本机);如果是​​Reduce​​​ 进程,将结果数据写出到​​HDFS​​。


(2)​​MR​​数据合并与连接机制

主要是:​​shuffle​​过程

​shuffle​​​:在 ​​map​​​ 输出与 ​​reduce​​​ 输入之间,​​MapReduce​​ 计算框架处理数据合并与连接操作。

分布式计算需要将不同服务器上的相关数据合并到一起进行下一步计算

如下图:

【MapReduce】之 工作原理_服务器_03

每个 ​​Map​​​ 任务的计算结果都会写入到本地文件系统,等 ​​Map​​​ 任务快要计算完成的时候,​​MapReduce​​​ 计算框架会启动 ​​shuffle​​​ 过程,在 ​​Map​​​ 任务进程调用一个 ​​Partitioner​​​ 接口,对 ​​Map​​​ 产生的每个 ​​<key, value>​​​ 进行 ​​Reduce​​​ 分区选择,然后通过 ​​HTTP​​​ 通信发送给对应的 ​​Reduce​​​ 进程。这样不管 ​​Map​​​ 位于哪个服务器节点,相同的 ​​Key​​​ 一定会被发送给相同的 ​​Reduce​​​ 进程。​​Reduce​​​ 任务进程对收到的 进行排序和合并,相同的 ​​Key​​​ 放在一起,组成一个 传递给 ​​Reduce​​ 执行。

​map​​​ 输出的 ​​shuffle​​​ 到哪个 ​​Reduce​​​ 进程是这里的关键,它是由 ​​Partitioner​​​来实现,​​MapReduce​​​ 框架默认的 ​​Partitioner​​​ 用 ​​Key​​​ 的哈希值对 ​​Reduce​​​任务数量取模,相同的 ​​Key​​​ 一定会落在相同的 ​​Reduce​​​ 任务 ID 上。从实现上来看的话,这样的 ​​Partitioner​​ 代码只需要一行。

public int getPartition(K2 key, V2 value, int numReduceTasks) {
return (key.hashCode() & Integer.MAX_VALUE) % numReduceTasks;
}