起源
做搜索是技术难度很高的活。首先要存储很多的数据,要把全球的大部分网页都抓下来,可想而知存储量有多大。然后,要能快速检索网页,用户输入几个关键词找资料,越快越好,最好在一秒之内出结果。如果全球每秒有上亿个用户在检索,只有一两秒的检索时间,要在全球的网页里找到最合适的检索结果,难度很大。
Google 用三个最重要的核心技术解决上述问题,它们分别是 GFS、 MapReduce 和 BigTable。Google 发表了它们的设计论文,但没有将它们开源,核心竞争力不可能开源的。论文发表之后,Doug Cutting 等人根据论文的思想,在开源项目 Nutch 的基础上实现了 Hadoop。后来,Doug Cutting 去了Yahoo,继续做 Hadoop。后来,Hadoop 的开发和应用开始爆发了。
在对应关系上看,Hadoop MapReduce 对应 MapReduce,Hadoop Distributed File System (HDFS)对应 GFS,HBase对应 BigTable。一般我们所说的Hadoop 其实是指 Hadoop 体系,它包括 Hadoop MapReduce、HDFS、HBase,还有其他更多的技术。
工作原理
先用一种有助于理解的方式描述 MapReduce 和 HDFS 是如何工作的。假如有1000G 的多个文本文件,内容是英文网页,需要统计词频,也就是哪些单词出现过,各出现过多少次,有 1000 台计算机可供使用,要求速度越快越好。
最直接的想法是,把 1000G 的文件分成 1000 份,每台机器处理 1G 数据。处理完之后,其他 999 台机器将处理结果发送到一台固定的机器上,由这台机器进行合并然后输出结果。
Hadoop 将这个过程进行自动化的处理。首先看如何存储这1000G 的文本文件。HDFS在这1000台机器上创建分布式文件系统,将 1000G 的文件切分成若干个固定大小的文件块,每个块一般是 64M 大小,分散存储在这 1000 台机器上。这么多机器,在运行的时候难免会出现有几台突然死机或者挂掉的情况,这导致上面存储的文件块丢失,会导致计算出错。为避免这种情况,HDFS 对每个文件块都做复制,复制成 3~5 个相同的块,放到不同的机器上,这样死机的文件块在其他机器上仍然可以找得到,不影响计算。
MapReduce 其实是两部分,先是 Map 过程,然后是 Reduce 过程。从词频计算来说,假设某个文件块里的一行文”字是“ This is a small cat. That is a small dog.”,那么,Map 过程会对这一行进行处理,将每个单词从句子解析出来,依次生成形如<“this”, 1>, <”is”, 1>, <”a”, 1>, <”small”, 1>, <”cat”, 1>, <”that”, 1>, <”is”, 1>, <”a”, 1>, <”small”, 1>,<”dog”, 1>的键值对,<”this”, 1> “ 表示 this”这个单词出现了 1次,在每个键值对里,单词出现的次数都是 1 次,允许有相同的键值对多次出现,比如<”is”,1>这个键值对出现了 2 次。Reduce 过程就是合并同类项,将上述产生的相同的键值对合并起来,将这些单词出现的次数累加起来,计算结果就是<“this”, 1>, <”is”, 2>, <”a”, 2>, <”small”, 2>,<”cat”, 1>, <”that”, 1>, <”dog”, 1>。
这种方式很简洁,并且可以进行多种形式的优化。比如说,在一个机器上,对本地存储的 1G 的文件块先 Map,然后再 Reduce,那么就得到了这 1G 的词频统计结果,然后再将这个结果传送到远程机器,跟其他 999 台机器的统计结果再次进行 Reduce,就得到 1000G 文件的全部词频统计结果。如果文件没有那么大,只有三四个G,就不需要在本地进行Reduce 了,每次 Map 之后直接将结果传送到远程机器做 Reduce。
具体地,如果用Hadoop 来做词频统计,流程是这样的:
1) 先用HDFS的命令行工具,将1000G 的文件复制到 HDFS 上;
2) 用Java 写MapReduce 代码,写完后调试编译,然后打包成 Jar 包;
3) 执行Hadoop 命令,用这个 Jar 包在 Hadoop 集群上处理 1000G 的文件,然后将结果文件存放到指定的目录。
4) 用HDFS的命令行工具查看处理结果文件。