Hadoop 基本原理
Hadoop 使用 MapReduce 算法以及分布式文件系统处理大数据。使用 Hadoop 重点需要理解 MapReduce 算法。
MapReduce 算法需要实现 Mapper 和 Reducer 两个部件。数据在算法内部一般以 Key-Value 对的形式传递。算法输入是一组 Key-Value 对,Mapper 首先处理该 Key-Value 对并将其转换为另一组 Key-Value 对,Reducer 接收排序后的 Mapper 输出并输出另一组 Key-Value 对作为最终输出。
从 MapReduce 的经典例子 WordCount 问题理解该算法的意义。考虑从大量文本中统计词频。首先,文本被分割成适当大小的文件。首先会启动许多 Mapper 实例处理这些文件。Mapper 实例的输入应该是 Key-Value 对,但是很多情况下(如 WordCount 问题或者处理数据库表格时) Key 常常是行号等序号,因此每个 Mapper 读取一些行。用于 WordCount 的 Mapper 可以是一般的 WordCount 程序,统计词频,并输出 (Word, Count) 作为 Key-Value 对。重点在于,接下来 Hadoop 会负责对所有 Mapper 输出的 (Word, Count) 对关于 Word 排序,然后分割之后按顺序输出给 Reducer 处理。具有相同 Key 的 Mapper 输出对一定会被输出到同一个 Reducer 处理(但是一个 Reducer 可能会收到不止一个 Key)。在 WordCount 问题中,相同 Word 对应的 (Word, Count) 对会被输出到同一个 Reducer, 此后 Reducer 就可以对 Count 求和得到该问题的最终解。
该算法的重点在于 Hadoop 将 Mapper 的输出排序,因此单个 Reducer 能够看到该 Key 在数据集中相关的全部信息,因此进行跟全部数据相关的计算成为可能。
Hadoop Streaming Example
Hadoop 使用 Java 开发,其 Mapper & Reducer 默认用 Java 实现。但是也可以借助 Hadoop Streaming, 搭配 STDIO, 即可使用任何标准命令行工具充当 Mapper & Reducer. 下面给出一个使用 Python 实现的 WordCount 例子。在 Hadoop 3.1.1 下测试通过。
在下载的 Hadoop 二进制包解压得到的目录中创建 Input Script 两个目录。Input 目录存放输入文件,每个文件会被发给一个 Mapper (因此在真正的应用场景中,文件应该有恰当的大小)。Script 目录存放本例使用的两个 Python 脚本,分别是:
# ==== file: mapper.py ====
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import print_function
from __future__ import division
import sys
from collections import defaultdict
counter = defaultdict(lambda: 0)
for line in sys.stdin:
for word in line.split():
counter[word] += 1
for key, val in counter.items():
print("%s\t%s" % (key, val))
# ==== file: reducer.py ====
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import print_function
from __future__ import division
import sys
from collections import defaultdict
counter = defaultdict(lambda: 0)
for line in sys.stdin:
line = line.split()
counter[line[0]] += sum(int(word) for word in line[1:])
for key, val in counter.items():
print("%s\t%s" % (key, val))
运行命令:
bin/mapred streaming \
-input Input \
-output Output \
-mapper Script/mapper.py \
-reducer Script/reducer.py
即可在 Output 目录中得到统计结果。