|
MapReduce 是 Hadoop 生态下的海量数据计算框架。利用它可以快速开发出处理海量数据的应用程序,并且应用程序是以并行的方式运行在由价格低廉的机器组成的大规模集群之上的。
MapReduce 任务由 Map 任务和 Reduce 任务组成。每个任务负责计算一部分数据,这样将会把工作负载分发到各个机器上面。Map 任何的主要工作是加载,解析,转换和过滤数据,而 Reduce 任务则是处理来自 Map 任务输出的数据,它会对这些 map 输出的中间数据结果进行分组和聚合操作。
MapReduce 处理的输入文件是存放在 HDFS 上的,如何把文件分割成数据分片取决于文件的输入格式(inputformat),数据分片其实是输入文件数据块的字节形式,map 任何会加载这些数据分片,map 任务会尽量在离数据最近的 datanode 机器上执行。这样数据就不需要通过网络传输,而是在本地就能对数据进行处理,避免了带宽资源的消耗。
\
Map任务
Map任务分为以下阶段:
RecordReader
RecordReader 会把输入分片转换成记录,它将数据解析为记录,但不解析记录本身。接着把数据以键值对的方式提供给 mapper 函数,一般键是记录的位移信息,而值是具体的数据记录。一个键值对就是一条记录。
Map
在这一阶段,用户定义的 mapper 函数会处理来自 recordreader 输出的键值对数据,并输出0个或者多个中间键值对结果。
键值对具体如何被处理取决于你开发的mapper函数,通常情况下,reduce函数会利用键做分组操作,而值会根据键做聚合计算并产生最终的结果。
Combiner
Combiner 其实也是 reduce 操作,只是它是在 map 阶段做数据聚合操作,并且这是一种可选的操作,即你可以不使用 Combiner,但是在必要的时候使用它会提高任务执行效率。Combiner 从 mapper 获取中间数据,并对这些数据进行聚合。在很多情况下,使用 Combiner 可以减少网络传输的数据量。例如,传输3次(Hello World, 1)比传输一次(Hello World, 3)要消耗更多的带宽资源。
Partitioner
partitioner 从 mapper 拉取键值对数据结果,它会把这些数据分割成分片,每个 reducer 一个分片。默认情况下,partitioner 会对键取哈希值并和reducer 的数量取模运算:key.hashcode() % reducer 数量。这样就可以把键均匀的分发到每个 reducer,还可以确保具有相同 key 的数据落到落在同一个 reducer。被分区的数据将会被写到本地文件系统,等待响应的 reducer 来拉取。
Reduce任务
reduce 任务分为以下几个阶段:
Shuffle和排序
shuffle 和排序操作是 reducer 的起始步骤,该阶段会把 partitioner 输出到文件系统的数据拉取到 reducer 所执行的机器上,并对数据做排序操作形成一个大的数据列表,排序的目的是把相同键的数据聚集在一起,当然,这些操作是由MapReduce框架自动完成的,我们不能对这些操作做改动。但是我们可以通过comparator 对象对键的排序和分区规则进行定制化开发。
Reduce
reducer 会对每个的键对应的分组做 reduce 操作。mapreduce 框架把键和一个包含该键的所有值的迭代对象传递给 reduce 函数。
我们可以开发 reducer 来对数据进行不同方式的过滤、聚合以及连接操作。reduce函数执行完之后,它会把生成的0个或者多个键值对传递给 outputformat。
OutputFormat
这是最后一步,它接收 reducer 的键值对数据,并通过 recordwrite 把它们写到文件。默认情况下,它是用 tab 分隔符分割键和值,用换行符分割记录。你可以开发其他的 outputformat 来定制修改这个默认规则。但最终的数据都会被写到 HDFS。
![](https://www.hadoopdoc.com/media/editor/mapreduce-work_20191001231307953395.png)
|
|