1. 直观理解
想要统计一堆牌中有多少张黑桃,最简单的方法是一张一张去数。而 MapReduce 则是让多个玩家来并行地统计,从而大大缩短统计时间:
- 把这堆牌分配给多个玩家;
- 让每个玩家统计自己手中有多少张黑桃;
- 把所有玩家统计的黑桃数量加起来就是最终的结果。
2. 分而治之
某些计算任务能够并行地执行,这些任务可拆分并且不能有数据依赖。例如斐波那契数列 f(n) = f(n-1) + f(n - 2),第 n 项的计算依赖于第 n - 1 项和第 n - 2 项的计算结果,因此不能并行执行。但是对于将一个二维数组中每个元素都进行加 1 的计算,每个元素的计算都没有数据依赖,因此能够并行。
3. 基本原理
MapReduce 用来对海量数据进行离线分析,通过将计算任务分配给集群的多台机器,使得这些计算能够并行地执行。
它分为 Map 和 Reduce 两个阶段:
- Map(映射):对每个目标应用同一操作;
- Reduce(归纳):整合部分结果。
在下图中,
- file 被划分为多个 split,每个分片由一个 Mapper Task 去处理。Map 过程中输入的是 [K1, V1] 数据,这是一种键值对形式的数据,键为泛型的 K1 类型,值为泛型的 V1 类型。输出也是一个泛型的键值对 [K2, V2]。
- Shuffle 过程主要是对 Map 阶段输出的键值对进行整合,将键相同的键值对整合到一组中,得到 [K2, {V2,...}] 的整合数据,作为 Reudce 阶段的输入。
- Reduce 处理完之后得到 [K3, V3] 键值对,Hadoop 会将输出的数据存到分布式文件系统 HDFS 中。
4. WordCount 实例
WordCount 用于对文本进行词频统计。
4.1 文本
-
the weather is good
-
today is good
-
good weather is good
-
today has good weather
将文本的每一行拆成分片,每个分片的数据提供给 Mapper 进行处理,因此需要 4 个 Mapper。其中 K1 为行号,V1 为该行的字符串。
-
Split-0: [0, "the weather is good]
-
Split-1: [1, "today is good"]
-
Split-2: [2, "good weather is good"]
-
Split-3: [3, "today has good weather]
4.2 Mapper
将输入的字符串 V1 进行切分,输出 K2 为单词, V2 为词频。
-
Mapper-0: ["the", 1], ["weather", 1], ["is", 1], ["good", 1]
-
Mapper-1: ["today", 1], ["is", 1], ["good", 1]
-
Mapper-2: ["good", 2], ["weather", 1], ["is", 1]
-
Mapper-3: [today", 1], ["has", 1], ["good", 1], ["weater", 1]
4.3 Shuffle
排序并将拥有相同键的数据整合,得到 [K2, {V2,...}]。
-
["good", {1, 1, 2, 1}]
-
["has", {1}]
-
["is", {1, 1, 1}]
-
["the", {1}]
-
["today", {1, 2}]
-
["weater", {1,1}]
4.4 Reducer
遍历 Shuffle 阶段输出的 {V2,...} 集合,进行最终的统计。
-
Reducer-0: ["good", 5]
-
Reducer-1: ["has", 1]
-
Reducer-2: ["is", 3]
-
Reducer-3: ["the", 1]
-
Reducer-4: ["today", 2]
-
Reducer-5: ["weather", 3]