第零章 Mac上虚拟机安装与配置
第一章 Hadoop集群搭建
第二章 HDFS
第三章 MapReduce
第四章 YARN
第五章 Flume - 尚未更新
第六章 Hive
第七章 Scala - 尚未更新
第八章 Spark - 尚未更新
第九章 数据仓库 - 尚未更新
第十章 Kafka - 尚未更新
第十一章 Redis - 尚未更新
第十二章 Flink - 尚未更新
文章目录
前言
本章包含了Map和Reduce原理剖析以及WordCount案例实操
一、MapReduce 和 分布式计算 介绍
HDFS负责海量数据存储,数据处理、分析过程由MapReduce实现
传统的计算方式,是先提取数据到执行计算的机器,由机器计算完后,再输出结果,称之为 移动数据
这种方式,在数据量很大的时候,数据传输会严重影响整个计算流程耗时
为此,与其移动数据,不如移动计算程序,因为通常计算程序代码的文件大小很小,和几十G的数据文件相比,移动程序 到数据所在的机器,其传输时间,对计算流程的影响不大
分布式计算:
计算程序移动到分布的数据的每个节点上,计算完各自节点上的数据,输出的结果,需要通过汇总程序,得出最终的结果。
分布式计算包含两个步骤:
- 对每个节点上的数据进行局部计算;
- 对每个节点上面计算的结果,进行汇总
二、MapReduce 原理
文件被分成多个block
块存储,这是物理切分;
而split
是逻辑划分,不是对文件真正的划分。默认情况下,可以认为split
的大小和一个block
的大小一致。
如果,split跨block,甚至跨datanode的情况下,如何处理?
三、WordCount 案例
需求:统计文件中每个单词出现的总次数
文件示例:
hello world
hello Benjamin
...
每一行包含若干个单词,单词由空格符
" "
区隔,每一行由换行符"\n"
区隔
步骤分析:
- 将文件按行分割
- 再分割每一行中的单词
- 统计各个单词的数量
用MapReduce实现:
1. Map阶段
实现按行分割以及单词分割
- 在输入之前,框架会实现按行分割,具体如下:
输入:<k1, v1>
输出:<k2, v2>
<k1, v1>
是通过把文件划分成若干InputSplit
, 也就是之前提到的split
(对文件的逻辑划分),
再通过RecordReader
类,将每个InputSplit
解析成<k1, v1>
的形式
其中,k1
表示每一行的起始偏移量,v1
表示每一行的内容
根据示例,map阶段会输入:
<0, hello world>
<10, hello Benjamin>
- 通过编写Map阶段中Mapper类的
map
函数, 实现单词分割
(为了逻辑清晰,代码放在第四小节中)
根据示例,输出:
<hello, 1>
<world, 1>
<hello, 1>
<Benjamin, 1>
- MR框架会对输出的
<k2, v2>
进行分区,交由不同的reduce task
进行处理。
默认只有一个分区。当业务逻辑复杂的情况下,会产生多个reduce task
,此时,map
任务需要考虑输出的结果分配给哪个reduce
任务
- MR框架对每个分区中的数据,按照
k2
进行排序、分组。
排序后结果:
<Benjamin, 1>
<hello, 1>
<hello, 1>
<world, 1>
分组, 将相同的k2
, v2
分成一组,分组后结果:
<Benjamin, {1}>
<hello, {1, 1}>
<world, {1}>
- 可选执行
combiner
过程
可以在此过程中提前执行reduce
的计算逻辑,减少从map
端到reduce
端数据传输的大小。
默认此过程不执行,
- 输出
<k2, {v2}>
到磁盘文件
2. Reduce阶段
统计各个单词的数量
输入:<k2, {v2}>
输出:<k3, v3>
shuffle
过程
从磁盘文件拷贝map
阶段输出的结果<k2, {v2}>
到reduce
节点
- 对相同分区的
<k2, {v2}>
数据进行合并、排序、分组。
此时的排序是多个map结果的全局排序
- 编写Reducer类中的reduce方法,实现
{v2}
的聚合计算操作
(为了逻辑清晰,代码放在第四小节中)
输出:
<Benjamin, 1>
<hello, 2>
<world, 1>
- 将结果保存到HDFS中
Benjamin 1
hello 2
world 1
四、实现WordCount 案例
1. 代码
package com.imooc.mr;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io