Hadoop学习笔记(2):MapReduce 基础编程

MapReduce 采用“分而治之”的思想,把对大规模数据集的操作,分发给一个主节点管理下的各个分节点共同完成,然后通过整合各个节点的中间结果,得到最终结果。简单地说,MapReduce 就是“任务的分解与结果的汇总”。

在 Hadoop 中,用于执行 MapReduce 任务的机器角色有两个:

  • JobTracker 用于调度工作的,一个 Hadoop 集群中只有一个 JobTracker,位于 master
  • TaskTracker 用于执行工作,位于各 slave 上

在分布式计算中,MapReduce 框架负责处理了并行编程中分布式存储、工作调度、负载均衡、容错均衡、容错处理以及网络通信等复杂问题,把处理过程高度抽象为两个函数:map 和 reduce,map 负责把任务分解成多个任务,reduce 负责把分解后多任务处理的结果汇总起来。

需要注意的是,用 MapReduce 来处理的数据集(或任务)必须具备这样的特点:待处理的数据集可以分解成许多小的数据集,而且每一个小数据集都可以完全并行地进行处理。

WordCount

修改 WordCount 源代码,使得输出的词频统计满足

  • 数据清洗:对每个词的格式进行规范化(去除不以英文字母开头的所有词)
  • 词频少于 3 次的数据不在结果中显示
  • 结果以有限数量的“+”表示词频统计

因此,

  • 在 map 函数中进行修改,只有当单词以英文字母开头(此处可考虑使用正则表达式进行匹配)时,才将其输出。
  • 在 reduce 中进行判断,只有当 reduce 函数的 Key 的 Value 之和大于 3,才将其作为 reduce 函数的输出。
  • 由于 reduce 所输出的 Key 与 Value 的类型均为 Text 类型,需要修改 reduce 函数的输出类型,并修改配置文件中的输出类型。

我们这里采用的是古德堡项目中的部分英文小说,部分运行结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
abaft    +++
abandon +++++
abandoned +++++++++++++++++++++
abandoning +++
abandonment ++++
abated +++++
abbey +++
abed ++++
abhorred ++++
abide ++++++++++++++++++
ability ++++
abject +++

Source Code

InvertedIndex

倒排索引是目前几乎所有支持全文检索的搜索引擎都需要依赖的一个数据结构,该索引结构用来存储某个单词在一个文档或一组文档中存储位置的映射,即提供了一种根据内容来查找文档的方式。

改进 WordCount 代码:Map 函数输出 <单词,文件名@位置>,Reduce 函数输出 <单词,list<文件名@位置>>即可。

  • 清洗一部分明显不合理的单词的统计
  • 根据上述要求,完成真实环境中文档倒排索引的 MapReduce 框架代码
  • 生成一个 input 文件夹,搜索一个文本文件的集合,拷贝到 input 文件夹中
  • 运行 MapReduce 框架将生成的倒排文档索引放入目标文件中

因此,

  • 通过查询相关文献,我们采取删除在 StopWords 的单词的方法。与在 WordCount 中一样,只有当单词不在 StopWords 列表中时,才将其输出。
  • 在此处若直接将键值对 <单词,文件名> 作为 Reduce 的输入,在数据量极大时,会因为网络带宽,对性能造成极大地降低,那么我们是否可以先在 map 服务器上对键值对进行合并,那么传递给 Reduce 的输入的数据量就会大大减少。基于这个思想,我们在此处使用 Combiner 函数对 map 的输出进行预先的合并。
  • 此处还需要注意一点,这里要求输出单词在文件中的位置,而 map 是按行进行读入的,并不像我们平常使用的 Java 读入文件那样,可以可以根据换行符来判断他在第几行。这里,由于文件名或者说文件的存储路径是不同的,我们可以使用其来进行判断他是否属于同一个文件,若属于同一个文件,我们对行数加一,若不属于同一个文件,我们将行数归为 1。因此,我们就实现了判断单词在文件中的位置。

我们这里采用的是古德堡项目中的部分英文小说,部分运行结果如下:

1
2
3
aback    98-0.txt@70690;pg345.txt@55123;2701-0.txt@12402;2701-0.txt@5472;
abaft 2701-0.txt@15814;2701-0.txt@9732;pg345.txt@51608;pg345.txt@51265;
abandon pg345.txt@55383;2701-0.txt@8558;2701-0.txt@944;2701-0.txt@15471;98-0.txt@69667;

Source Code

在编写代码时,我遇到了这样一个问题,就是因为 Combiner 的输入与输出类型与 map 的输出和 reduce 的输入不同而报错。通过查阅相关资料,了解到 Combiner 的输入和 reduce 的完全一致,输出和 map 的完全一致。

在结果中,我们看到因为英语有单复数、时态等,相同的单词可能被认为是不同的,查阅相关资料,我们了解到可以用词干提取与词干还原等方式将单词变为原型。