大家好,今天给大家介绍一下如何建立MapReduce程序的基本模板
MapReduce程序与您所学过的编程模型有所不同。您需要花一些时间,并进行一些练习来熟悉它。为了帮助您精通它,我们在后面几章会通过多个例子来进行练习。这些例子描述了不同的MapReduce编程技术。通过用不同方式应用MapReduce,您可以开始培养一种直觉,并养成“用MapReduce思考(thinking in MapReduce)”的习惯。这些例子包括了简单的例子和高级的应用。在一个高级的应用程序中,我们介绍了Bloom滤镜,一种在标准的计算机科学课程中不会讲授的数据结构。您会了解到处理大量的数据集时,无论您是否使用Hadoop,通常都会需要重新考虑底层的算法。
我们假设您已经掌握了Hadoop的基础,您可以建立Hadoop,并编译和运行示例程序,例如第一章中的单词统计的例子。我们将以现实世界中的数据集为例来进行学习。
要用Hadoop做一点有意义的事情的话,我们需要数据。我们的许多例子会使用专利数据集,可以从全国经济研究局(NBER)的网址http://www.nber.org/patents/获取这些数据。这些数据集最初是为论文《NBER专利引用数据文件:经验,见解和方法工具》编制的。我们将使用专利引用数据集cite75_99.txt和专利描述数据集apat63_99.txt。
请注意
每个数据集有将近250MB,这对于我们的以独立或伪分布模式运行的Hadoop而言是足够小的。您可以使用它们练习编写MapReduce程序,甚至不需要访问一个集群。Hadoop最好的一个方面是您可以很确定您的MapReduce程序可以在集群机上运行,处理100或者1000倍的数据,而几乎不需要改动任何代码。
一个开发中经常涉及的话题,是为您的大量的生产数据建立较小的用于示范的子集,这也被称为开发数据集。这些开发数据集可能只有几百兆。这将缩短您的开发进程中的,在开发与生产环境之间切换所需要的往返时间,便于您在自己的机器上运行,并在另一个独立的环境中进行调试。
我们选择这两个数据集是因为它们与您遇到的大多数数据类型相似。首先,这些引用数据构成了一个“图”,而用于描述网络连接和社交网络的数据结构也是图。专利是按时间顺序公布的,它们的一些属性表示了时间序列。每个专利都与一个人(发明者)和一个地点(发明者所在的国家)。您可以将它们看作个人或者地理信息。最后您可以将这些数据看作定义良好的数据库关系,它们以逗号分隔。
请注意有很多这两个数据集无法完全表现的数据类型,例如文本,但您已经在单词计算的例子里见过文本了。其他没有涉及的类型包括XML、图像和地理位置信息(用经纬度的形式表示)。数学矩阵没有以一般的形式表示,尽管引用图可以被解释为离散的0/1矩阵。
专利引用数据
这些专利引用数据包含了美国从1975年到1999年之间发布的引用。它有超过1600万行数据,并且前几行包含类似这样的信息:
以专利数据集65为例:
“CITING”,”CITED”
3858241,956203
3858241,1324234
3858241,3398406
3858241,3557384
3858241,3634889
3858242,1515701
3858242,3319261
3858242,3668705
3858242,3707004
数据集以标准的逗号分隔值(CSV)格式表示,第一行是列的描述。其他的每一行记录了一个特定的引用。例如,第二行表示专利3858241引用了专利956203。文件是按照进行引用的专利(而不是被引用的专利)进行排序的。我们可以看到专利3858241总共引用了五个专利。更定量地分析这些数据可以使我们对它有一个更深入的了解。
如果您只是阅读这个数据文件,引用数据看起来好像只是一系列的数据。您可以用更有趣的术语来考虑这些数据。一种方式是将它想象为一张图。在图 4.1中,我们展示了这张引用图的一部分。我们可以看到有些专利经常被引用,而另一些则从来没有被引用过。专利5936972和6009552引用了类似的专利集合(4354269, 4486882, 5598422),尽管它们没有相互引用。我们可以使用Hadoop来获取关于这些专利数据的描述性的数据,并寻找有趣的但不那么明显的专利。
专利描述数据我们使用的另一个数据集是描述数据。它包含了专利号、专利申请年份、专利授予年份、索赔金额和其他关于专利的元数据。看看这个数据的前面几行。它与一个关系型数据库中的表格很相似,但它是CSV格式的。这个数据集有超过290万行记录。和现实世界中的很多数据集一样,它可能有丢失的数据
专利描述数据“PATENT”,”GYEAR”,”GDATE”,”APPYEAR”,”COUNTRY”,”POSTATE”,”ASSIGNEE”,
➥ ”ASSCODE”,”CLAIMS”,”NCLASS”,”CAT”,”SUBCAT”,”CMADE”,”CRECEIVE”,
➥ ”RATIOCIT”,”GENERAL”,”ORIGINAL”,”FWDAPLAG”,”BCKGTLAG”,”SELFCTUB”,
➥ ”SELFCTLB”,”SECDUPBD”,”SECDLWBD”
3070801,1963,1096,,”BE”,””,,1,,269,6,69,,1,,0,,,,,,,
3070802,1963,1096,,”US”,”TX”,,1,,2,6,63,,0,,,,,,,,,
3070803,1963,1096,,”US”,”IL”,,1,,2,6,63,,9,,0.3704,,,,,,,
3070804,1963,1096,,”US”,”OH”,,1,,2,6,63,,3,,0.6667,,,,,,,
3070805,1963,1096,,”US”,”CA”,,1,,2,6,63,,1,,0,,,,,,,
3070806,1963,1096,,”US”,”PA”,,1,,2,6,63,,0,,,,,,,,,
3070807,1963,1096,,”US”,”OH”,,1,,623,3,39,,3,,0.4444,,,,,,,
3070808,1963,1096,,”US”,”IA”,,1,,623,3,39,,4,,0.375,,,,,,,
3070809,1963,1096,,”US”,”AZ”,,1,,4,6,65,,0,,,,,,,,,
请注意
和其他数据分析一样,我们在解释这些有限的数据时需要非常地谨慎。如果一个专利看起来没有引用任何其他的专利,它可能是我们没有引用信息的旧的专利。另一方面,时间越晚的专利被引用的频率更小,因为只有更新的专利才会意识到它们的存在。
属性名称 | 内容 |
PATENT | 专利号 |
GYEAR | 授权年份 |
GDATE | 授权日期, 从1960年1月1日算起的日期数 |
APPYEAR | 申请日期(只对1967年之后授权的专利有效) |
COUNTRY | 第一发明人的国家 |
POSTATE | 第一发明人所在的州(如果国家是美国) |
ASSIGNEE | 专利受让人的数字标识(例如,专利拥有者) |
ASSCODE | 一位数(1-9)表示的受让人类型。 (受让人类型包括美国个人,美国政府,美国组织,非美国个人,等等) |
CLAIMS | 索赔金额(只对1975年之后授权的专利有效) |
NCLASS | 三位数表示的专利类别 |
既然我们已经有了两个专利数据集,那么让我们编写Hadoop程序来处理这些数据吧。
建立MapReduce程序的基本模板
我们的大多数MapReduce程序是简短的并且是在一个模板上进行变化的。担负编写一个新的MapReduce程序时,您通常需要在一个现有的MapReduce程序上进行修改,直到它成为您想要的样子。在这个小节里,我们将编写第一个MapReduce程序并解释它的不同部分。这个程序可以作为将来的MapReduce程序的模板。我们的第一个程序将把专利引用数据作为输入,并将它反转。对每个专利,我们想要找出引用它的专利并将它们分组。
环境:Vmware 8.0 和Ubuntu11.04
Hadoop 实战之分析专利引用数据集(一)---计算专利引用数据并排序
第一步:首先创建一个工程命名为HadoopTest.目录结构如下图:
sudo rm -rf /tmp/*
rm -rf /home/tanglg1987/hadoop-0.20.2/logs
hadoop namenode -format
hadoop datanode -format
start-all.sh
hadoop fs -mkdir input
hadoop dfsadmin -safemode leave
第三步:给start.sh增加执行权限并启动hadoop伪分布式集群,代码如下:
chmod 777 /home/tanglg1987/start.sh
./start.sh
执行过程如下:
第四步:上传本地文件到hdfs
在专利局http://data.nber.org/patents/网站下载专利数据
http://data.nber.org/patents/apat63_99.zip
hadoop fs -put /home/tanglg1987/cite75_99.txt input
五步:新建一个MyJob.java,代码如下:
package com.baison.action;
import java.io.IOException;
import java.util.Iterator;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapred.FileInputFormat;
import org.apache.hadoop.mapred.FileOutputFormat;
import org.apache.hadoop.mapred.JobClient;
import org.apache.hadoop.mapred.JobConf;
import org.apache.hadoop.mapred.KeyValueTextInputFormat;
import org.apache.hadoop.mapred.MapReduceBase;
import org.apache.hadoop.mapred.Mapper;
import org.apache.hadoop.mapred.OutputCollector;
import org.apache.hadoop.mapred.Reducer;
import org.apache.hadoop.mapred.Reporter;
import o