pagerank 的 mapreduce 实现

35
PageRank PageRank MapReduce MapReduce 的的 的的 2011-09 2011-09

Upload: theresa-yolanda

Post on 03-Jan-2016

212 views

Category:

Documents


0 download

DESCRIPTION

PageRank 的 MapReduce 实现. 2011-09. PageRank 算法介绍 PageRank 算法的 MapReduce 实现 实现一个简单的搜索引擎 WordCount 例程源码讲解. PageRank 算法介绍. PageRank 算法由 Google 创始人之一 Larry Page 提出,它是 Google 排名运算法则的一部分,是 Google 用来标识网页的等级 / 重要性的一种方法,是 Google 用来衡量一个网站好坏的重要标准之一。 - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: PageRank 的 MapReduce 实现

PageRankPageRank 的的 MapReduceMapReduce 实实现现

2011-092011-09

Page 2: PageRank 的 MapReduce 实现

PageRankPageRank 算法介绍算法介绍

PageRankPageRank 算法的算法的 MapReduceMapReduce 实现实现

实现一个简单的搜索引擎实现一个简单的搜索引擎

WordCountWordCount 例程源码讲解例程源码讲解

Page 3: PageRank 的 MapReduce 实现

PageRankPageRank 算法介绍算法介绍 PageRankPageRank 算法由算法由 GoogleGoogle 创始人之一创始人之一 Larry PagLarry Pag

ee 提出,它是提出,它是 GoogleGoogle 排名运算法则的一部分,是排名运算法则的一部分,是GoogleGoogle 用来标识网页的等级用来标识网页的等级 // 重要性的一种方法,重要性的一种方法,是是 GoogleGoogle 用来衡量一个网站好坏的重要标准之用来衡量一个网站好坏的重要标准之一。一。

GoogleGoogle 通过通过 PageRankPageRank 来调整结果,使那些更具来调整结果,使那些更具“等级“等级 // 重要性”的网页在搜索结果中的排名获重要性”的网页在搜索结果中的排名获得提升,从而提高搜索结果的相关性和质量。得提升,从而提高搜索结果的相关性和质量。该该算法的基本思想是被大量高质量网页引用(链算法的基本思想是被大量高质量网页引用(链接)的网页也是高质量网页。接)的网页也是高质量网页。

Page 4: PageRank 的 MapReduce 实现

PageRankPageRank 算法介绍算法介绍1 2

11 2

( ) ( )( ) ( )( ) (1 ) ( ... ) (1 )

( ) ( ) ( ) ( )

nn i

in i

PR t PR tPR t PR tPR A a a a a

C t C t C t C t

PR(A)PR(A) 是网页是网页 AA 的的 PageRankPageRank 值;值; aa 是一个权值,例如可以设定为是一个权值,例如可以设定为 0.50.5 ,经过,经过

多次迭代,多次迭代, PR(A)PR(A) 接近精确值;接近精确值; ttii 表示链向页面表示链向页面 AA 的第的第 ii 个网页;个网页; C(tC(tii)) 表示页面表示页面 ii 的链出链接数的链出链接数

Page 5: PageRank 的 MapReduce 实现

PageRankPageRank 算法介绍算法介绍

PageRankPageRank 算法的算法的 MapReduceMapReduce 实现实现

实现一个简单的搜索引擎实现一个简单的搜索引擎

WordCountWordCount 例程源码讲解例程源码讲解

Page 6: PageRank 的 MapReduce 实现

PageRankPageRank 的的 MapReduceMapReduce 实现实现 Step 1:Step 1: 分析一个页面的链接数并赋初值;分析一个页面的链接数并赋初值; Step 2:Step 2: 多次迭代计算页面的多次迭代计算页面的 PageRankPageRank 值;值; Step 3:Step 3: 根据根据 PageRankPageRank 值排序。值排序。

Page 7: PageRank 的 MapReduce 实现

Step1 Step1 分析页面链接数分析页面链接数Map:Map:-input: (0 , index.html)-input: (0 , index.html)-output: (index.html , 1.htm-output: (index.html , 1.htm

l)l) (index.html , 2.html)(index.html , 2.html) … … (index.html , n.html)(index.html , n.html)

说明:输出为说明:输出为 (key(key ,, value)value)键值对,键值对, keykey 为当前网页为当前网页路径,路径, valuevalue 为当前网页为当前网页中的对外的链接。中的对外的链接。

Reduce:

-input:

key: “index.html”

value: “1.html”,…,”n.html”

-output:

key: ”index.html”

value: “1.0 1.html,…,n.html”

说明: Hadoop 把 Map 函数输出的 key 合并,相同 key 的value 合并成一个集合作为 reduce 的 value 。输出 key 网页的 PR 值(初值为 1.0 )

Page 8: PageRank 的 MapReduce 实现

Step1 Step1 分析页面链接数分析页面链接数 对于 MapReduce 程序, Map 函数的输入为用户指定的文件,那么输入的 value 值就是文件内容(可以配置成按行读取或者把整个文件视作一个大字符串), key 值是读入文本的偏移量。程序员对输入的 key,value 进行一系列操作,然后按 (key,value) 键值对的形式输出。需要注意的是:输出的 key,value 是程序员自己定义的,可以和输入的 key,value 毫不相关。

系统获取 Map 函数的输出,把相同的 key 合并,再把key 和 value 集合作为键值对作为 reduce 函数的输入。程序员自定义 reduce 函数中的处理方法,输出 (key,value)键值对到磁盘文件。

Page 9: PageRank 的 MapReduce 实现

Step2 Step2 迭代计算迭代计算 PageRankPageRank 值值Map:Map:-input:-input: key: index.htmlkey: index.html value:<PR>1.html,2.html…value:<PR>1.html,2.html…

-output:-output: key: “1.html”key: “1.html” Value: “index.html<PR>Value: “index.html<PR> <number of outlinks>”<number of outlinks>” Key: “2.html”Key: “2.html” Value:” index.html<PR>Value:” index.html<PR> <number of outlinks>”<number of outlinks>”…………

Reduce:

-input:

Key: “1.html”

Value: ”index.html 0.5 23”,

”2.html 2.4 2”,……

key: “2.html”

value: “index.html 0.5 23”,

“1.html 1.3 3”,……

-output:

key:”1.html”

value:“<new PR>

index.html,2.html”

<PageRank>

<number of outlinks>

注意,这是 1.html 的新 PR 值

Page 10: PageRank 的 MapReduce 实现

Step2 Step2 迭代计算迭代计算 PageRankPageRank 值值说明:说明:

step2step2 是一个迭代过程,每次将磁盘上的文件读是一个迭代过程,每次将磁盘上的文件读入,入, keykey 为每一个网页链接,为每一个网页链接, valuevalue 的第一项为当前的第一项为当前网页的网页的 PangRankPangRank 值,后面接该网页中的对外链接。值,后面接该网页中的对外链接。MapMap 函数将输入的每一对函数将输入的每一对 (key,value)“(key,value)“ 反转”成多反转”成多对对 (value,key)(value,key) 输出,也就是说,输出,也就是说,每个输出的每个输出的 keykey 为为输入输入 valuevalue 中的每一个链接,而输出中的每一个链接,而输出 valuevalue 为输入为输入 kekeyy 的链接的链接 ++ 输入输入 keykey 的的 PRPR 值值 ++ 输入输入 keykey 的对外链接的对外链接数。数。

在在 reducereduce 函数中,就可以根据输入的函数中,就可以根据输入的 valuevalue 中中的参数来计算每一个的参数来计算每一个 keykey 新的新的 PageRankPageRank 值,并按值,并按 MMapap 函数的格式输出到磁盘,以作为下一次迭代的输入。函数的格式输出到磁盘,以作为下一次迭代的输入。迭代多次后,迭代多次后, PageRankPageRank 值趋于稳定,就得出了较为值趋于稳定,就得出了较为精确的精确的 PageRankPageRank 值。值。

Page 11: PageRank 的 MapReduce 实现

Step3 Step3 根据根据 PageRankPageRank 值排序值排序Map:Map:

-input:-input: key: “index.html”key: “index.html” value: “<PR> 1.html,2.html”value: “<PR> 1.html,2.html”

-output:-output: key: “<PR>”key: “<PR>” value: “index.html”value: “index.html”

Page 12: PageRank 的 MapReduce 实现

Step3 Step3 根据根据 PageRankPageRank 值排序值排序说明:系统在处理说明:系统在处理 MapMap 函数的输出时,将把函数的输出时,将把

所有相同的所有相同的 keykey 合并,并合并,并排序输出排序输出到到 ReduReducece 函数的输入中。所以,函数的输入中。所以, MapMap 函数只需要函数只需要把把 PageRankPageRank 值作为值作为 keykey 输出,系统就会自输出,系统就会自动把动把 keykey 排序输出到排序输出到 reducereduce 函数。函数。 ReducReducee 函数只需依次输出每个函数只需依次输出每个 valuevalue 中的链接,中的链接,就得到了按就得到了按 PageRankPageRank 排序的网页链接。至排序的网页链接。至此,算法结束。此,算法结束。

Page 13: PageRank 的 MapReduce 实现

PageRankPageRank 算法介绍算法介绍

PageRankPageRank 算法的算法的 MapReduceMapReduce 实现实现

实现一个简单的搜索引擎实现一个简单的搜索引擎

WordCountWordCount 例程源码讲解例程源码讲解

Page 14: PageRank 的 MapReduce 实现

实现一个简单的搜索引擎实现一个简单的搜索引擎 Step1Step1 :安装:安装 HadoopHadoop 运行环境运行环境 Step2Step2 :获取网页集合存放到:获取网页集合存放到 HDFSHDFS 中中 Step3Step3 :编写:编写 MapReduceMapReduce 程序程序 *Step4*Step4:将输出结果存储到分布式数据库:将输出结果存储到分布式数据库

中中

Page 15: PageRank 的 MapReduce 实现

Step1 Step1 安装安装 HadoopHadoop 运行环境运行环境 11 ,安装,安装 linuxlinux 系统,如系统,如 Ubuntu11.04Ubuntu11.04,这,这

一步网上有详细的教程,请同学们自行学习一步网上有详细的教程,请同学们自行学习 22 ,在,在 linux linux 平台上安装平台上安装 HadoopHadoop 。在。在 HadoHado

op op 官网官网 ((http://hadoop.apache.org/http://hadoop.apache.org/ ) ) 下载下载一个一个 Hadoop Hadoop 版本:在以下页面中选择一个版本:在以下页面中选择一个镜像站点下载,获取镜像站点下载,获取 hadoop-0.20.2.tar.gzhadoop-0.20.2.tar.gz。。

http://www.apache.org/dyn/closer.cgi/hahttp://www.apache.org/dyn/closer.cgi/hadoop/common/doop/common/

Page 16: PageRank 的 MapReduce 实现

Step1 Step1 安装安装 HadoopHadoop 运行环境运行环境 33 ,在,在 UbuntuUbuntu 系统上安装系统上安装 openssh-server:openssh-server:$sudo apt-get install openssh-server$sudo apt-get install openssh-server

44,建立,建立 sshssh无密码登陆:无密码登陆:$ssh-keygen –t dsa –P ‘’ –f ~/.ssh/id_dsa$ssh-keygen –t dsa –P ‘’ –f ~/.ssh/id_dsa

该命令在该命令在 ~/.ssh~/.ssh目录生成目录生成 id_dsaid_dsa 和和 id_dsa.pubid_dsa.pub 密钥对,密钥对,我们把我们把 id_dsa.pubid_dsa.pub 追加授权到追加授权到 keykey里面 :里面 :

$cat ~/.ssh/id_dsa.pub >>~/.ssh/authorized_keys$cat ~/.ssh/id_dsa.pub >>~/.ssh/authorized_keys完成以后,就可以实现无密码登陆本机完成以后,就可以实现无密码登陆本机

$ssh localhost$ssh localhost 55 ,关闭防火墙:,关闭防火墙: $sudo ufw disable$sudo ufw disable

Page 17: PageRank 的 MapReduce 实现

Step1 Step1 安装安装 HadoopHadoop 运行环境运行环境 66,安装,安装 jdkjdk 。。

http://www.oracle.com/technetwork/java/javhttp://www.oracle.com/technetwork/java/javase/downloads/index.htmlase/downloads/index.html 安装路径为安装路径为 /home/uname/jdk/home/uname/jdk ,添加环境变量,添加环境变量到到 /etc/profile/etc/profile 中:中:

export JAVA_HOME=/home/uname/jdkexport JAVA_HOME=/home/uname/jdkexport JRE_HOME=/home/uname/jdk/jreexport JRE_HOME=/home/uname/jdk/jreexport CLASSPATH= export CLASSPATH= .:$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH.:$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH (注:网上有许多(注:网上有许多 jdkjdk 的安装教程,同学们可以的安装教程,同学们可以

参考)参考)

Page 18: PageRank 的 MapReduce 实现

Step1 Step1 安装安装 HadoopHadoop 运行环境运行环境 77,安装,安装 hadoophadoop 。。$ mv hadoop-0.20.2.tar.gz ~/hadoop-0.20.2.tar.g$ mv hadoop-0.20.2.tar.gz ~/hadoop-0.20.2.tar.gzz$cd ~$cd ~$ tar –zvxf hadoop-0.20.2.tar.gz$ tar –zvxf hadoop-0.20.2.tar.gz添加添加 hadoophadoop 的安装路径到的安装路径到 /etc/profile/etc/profile 中:中:export HADOOP_HOME=/home/uname/hadoop-export HADOOP_HOME=/home/uname/hadoop-

0.20.20.20.2export path=$HADOOP_HOME/bin:$PATHexport path=$HADOOP_HOME/bin:$PATH

Page 19: PageRank 的 MapReduce 实现

Step1 Step1 安装安装 HadoopHadoop 运行环境运行环境 88,配置,配置 hadoophadoop ::(1)$HADOOP_HOME/conf/hadoop-env.sh(1)$HADOOP_HOME/conf/hadoop-env.sh

中添加:中添加: export JAVA_HOME=/home/unexport JAVA_HOME=/home/uname/jdkame/jdk

(2)conf/masters(2)conf/masters 和和 conf/slavesconf/slaves 文件中,将文件中,将mastermaster 和和 slaveslave 的地址都改为的地址都改为 127.0.0.1127.0.0.1

(3)(3) 配置配置 conf/core-site.xml, conf/hdfs-site.conf/core-site.xml, conf/hdfs-site.xml, conf/mapred-site.xmlxml, conf/mapred-site.xml ::

Page 20: PageRank 的 MapReduce 实现

Step1 Step1 安装安装 HadoopHadoop 运行环境运行环境Core-site.xmlCore-site.xml<configuration><configuration>

<property><property><name>hadoop.tmp.dir</name><name>hadoop.tmp.dir</name><value>/home/uname/tmp</value><value>/home/uname/tmp</value>

</property></property><property><property>

<name>fs.default.name</name><name>fs.default.name</name><value>hdfs://127.0.0.1:9000</value><value>hdfs://127.0.0.1:9000</value>

</property></property></configuration></configuration>

Page 21: PageRank 的 MapReduce 实现

Step1 Step1 安装安装 HadoopHadoop 运行环境运行环境hdfs-site.xmlhdfs-site.xml<configuration><configuration>

<property><property><name>dfs.replication</name><name>dfs.replication</name><value>1</value><value>1</value>

</property></property></configuration></configuration>由于是只有一台机器的伪分布式,所以由于是只有一台机器的伪分布式,所以 replirepli

cationcation 必须设置为必须设置为 11 ,否则运行会报错,否则运行会报错

Page 22: PageRank 的 MapReduce 实现

Step1 Step1 安装安装 HadoopHadoop 运行环境运行环境mapred-site.xmlmapred-site.xml<configuration><configuration>

<property><property><name>mapred.job.tracker</name<name>mapred.job.tracker</name

>><value>127.0.0.1:9001</value><value>127.0.0.1:9001</value>

</property></property></configuration></configuration>

Page 23: PageRank 的 MapReduce 实现

Step1 Step1 安装安装 HadoopHadoop 运行环境运行环境 99,运行,运行 hadoophadoop ::$ cd $HADOOP_HOME$ cd $HADOOP_HOME$ cd bin$ cd bin格式化文件系统格式化文件系统$ hadoop namenode –format$ hadoop namenode –format启动启动 hadoophadoop$ start-all.sh$ start-all.sh用用 jpsjps 命令查看命令查看 javajava 进程,可以知道进程,可以知道 hadoohadoo

pp 是否启动成功是否启动成功

Page 24: PageRank 的 MapReduce 实现

Step1 Step1 安装安装 HadoopHadoop 运行环境运行环境 *10*10 ,安装,安装 eclipseeclipse ,进行,进行 hadoophadoop 开发开发

(( 在在 ubuntuubuntu 图形界面下安装图形界面下安装 eclipseeclipse ,也,也可以用可以用 apt-getapt-get 工具安装)。当然,也可以工具安装)。当然,也可以不使用不使用 eclipseeclipse ,直接用,直接用 vimvim编辑编辑 javajava 程程序,使用序,使用 javacjavac 手动编译手动编译 hadoophadoop 程序。程序。

Page 25: PageRank 的 MapReduce 实现

Step2 Step2 获取网页集合存放到获取网页集合存放到 HDFSHDFS中中

在网上下载一些网页(当然如果能用爬虫在网上下载一些网页(当然如果能用爬虫爬取最好),最好是英文网页,这样可以爬取最好),最好是英文网页,这样可以以空格来区分关键字。把网页保存到一个以空格来区分关键字。把网页保存到一个文件夹中,例如取名叫文件夹中,例如取名叫 web_setweb_set

把所有网页存放到把所有网页存放到 HDFSHDFS 中:中:$hadoop fs –copyFromLocal ./web_set dfs$hadoop fs –copyFromLocal ./web_set dfs_web_set_web_set

Page 26: PageRank 的 MapReduce 实现

Step3 Step3 编写编写 mapreducemapreduce 程序程序Map:Map:-input:-input:

key:0key:0value: x.htmlvalue: x.html

MapMap 函数内的操作:函数内的操作:读取读取 valuevalue 所代表的网页所代表的网页文件,提取出网页的文本文件,提取出网页的文本内容,按空格划分单词内容,按空格划分单词(参考(参考 WordCount.javaWordCount.java的写法)的写法)

-output:-output:key: wordkey: wordvalue: x.htmlvalue: x.html

Reduce:

-input:

key: word

value: <1.html,2.html,…>

Reduce 函数的操作:

对 value 中的网页根据 pageRank 排序。

-output:

key: word

value: 排序后的网页

Page 27: PageRank 的 MapReduce 实现

Step3 Step3 编写编写 mapreducemapreduce 程序程序 说明:这个程序和标准的说明:这个程序和标准的 wordcountwordcount 程序程序非常类似,请同学们仔细阅读非常类似,请同学们仔细阅读 hadoophadoop 源源码包当中的码包当中的 WordCount.javaWordCount.java 的源代码。的源代码。

Page 28: PageRank 的 MapReduce 实现

*Step4*Step4:将输出结果存储到分布式数据库中:将输出结果存储到分布式数据库中

这一步需要安装这一步需要安装 HBaseHBase 或者或者 CassandraCassandra 分分布式数据库,模拟布式数据库,模拟 googlegoogle 的的 bigtablebigtable 。。有兴趣的同学可以可以查阅一些关于有兴趣的同学可以可以查阅一些关于 HBasHBasee 或者或者 CassandraCassandra 的资料,把的资料,把 HadoopHadoop 的的计算结果存入到分布式数据库中,然后使计算结果存入到分布式数据库中,然后使用数据库提供的查询接口,就可以查出关用数据库提供的查询接口,就可以查出关键词所对应的网页了。(该步不作要求)键词所对应的网页了。(该步不作要求)

Page 29: PageRank 的 MapReduce 实现

PageRankPageRank 算法介绍算法介绍

PageRankPageRank 算法的算法的 MapReduceMapReduce 实现实现

实现一个简单的搜索引擎实现一个简单的搜索引擎

WordCountWordCount 例程源码讲解例程源码讲解

Page 30: PageRank 的 MapReduce 实现

mainmain 函数函数 public static void main(String[] args) throws Exception { Configuration conf = new Configuration(); String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs(); if (otherArgs.length != 2) { System.err.println("Usage: wordcount <in> <out>"); System.exit(2); } Job job = new Job(conf, "word count"); job.setJarByClass(WordCount.class); job.setMapperClass(TokenizerMapper.class); job.setCombinerClass(IntSumReducer.class); job.setReducerClass(IntSumReducer.class); job.setOutputKeyClass(Text.class); job.setOutputValueClass(IntWritable.class); FileInputFormat.addInputPath(job, new Path(otherArgs[0])); FileOutputFormat.setOutputPath(job, new Path(otherArgs[1])); System.exit(job.waitForCompletion(true) ? 0 : 1); }

Page 31: PageRank 的 MapReduce 实现

mainmain 函数函数

MapReduceMapReduce 的的 MainMain 函数的作用是做一些函数的作用是做一些系统的配置,例如初始化系统的配置,例如初始化 HadoopHadoop 的的 ConfiConfigurationguration 类,类, JobJob 类,设置类,设置 Map, ReduceMap, Reduce函数的输入输出参数类型,文件输入输出函数的输入输出参数类型,文件输入输出路径等工作。路径等工作。

MainMain 函数的编写有一些固定的规律和模式,函数的编写有一些固定的规律和模式,我们可以对照一些经典的我们可以对照一些经典的 MapReduceMapReduce 程程序或者参照一些编程文档来编写。序或者参照一些编程文档来编写。

Page 32: PageRank 的 MapReduce 实现

MapMap 函数函数1 private final static IntWritable one = new IntWritable(1);2 private Text word = new Text(); 3 public void map(Object key, Text value, Context context) 4 throws IOException, InterruptedException {5 StringTokenizer itr = new StringTokenizer(value.toString());6 while (itr.hasMoreTokens()) {7 word.set(itr.nextToken());8 context.write(word, one); } }

第 1,2 行, IntWritable 和 Text类我们可以看作就是一个 int类型和一个 string类型。由于 hadoop 使用了 JAVA RPC机制来实现通讯,所以调用的基本类型需要用对象来传递。因此 Hadoop 就用 IntWritable 和 Text类来对 int 和 string 进行封装,对 int 和文本内容进行存储、编码、解码,以此确保RPC 的高效执行。

Page 33: PageRank 的 MapReduce 实现

MapMap 函数函数第 3 行, Map 函数的第一个参数, key 是文本在文件中的偏移值,在这个程序中没有使用。

根据 Main 函数中的设置,第二个参数 value 是整个文件文本对象,因此第5 行 value.toString() 就把整个文本作为一个大字符串返回。该字符串返回到一个 StringTokenizer 的构造函数中。 StringTokenizer 是一个 java 自带的对象,用于分裂字符串。例如, new StringTokenizer(str , “,”) 就表示以逗号为分隔符,分裂字符串 str 。如果没有第二个参数,就是默认以空格作为分隔符。所以,第五行,就是把整个文本以空格分开成多个字符串(每个字符串就是一个单词了,因为单词以空格分开),保存到变量 itr 中。在接下来的循环语句中,就依次取出每个单词,并设置为 Text ,然后用 context.write() 输出。

Map 函数的第三个参数 context 是一个 hadoop 的类型, context.write() 方法用于输出一个键值对。 context.write(word,one) 就输出了一个单词和它的计数。每个单词的计数当然为 1 ,这个键值对输出到系统后,系统根据 key进行合并。例如,一个文本中含有 3 个单词 hello ,那么 map 函数就是输出 3 个键值对 (“hello”,1) ,系统根据 key 值进行合并,于是合并为 (“hello” , <1,1,1>) ,这个键值对就输入给 reduce 函数。

Page 34: PageRank 的 MapReduce 实现

ReduceReduce 函数函数1 private IntWritable result = new IntWritable();

2 public void reduce( Text key, Iterable<IntWritable> values, Context context)3 throws IOException, InterruptedException {4 int sum = 0;5 for (IntWritable val : values) {6 sum += val.get();7 }8 result.set(sum);9 context.write(key, result); }

看懂了 Map 函数, Reduce 函数应该很容易懂了。 Key 就是每一个单词,第 5~7 行的循环用于计算每一个 key 出现的次数。由于 map 函数中的输出是 context.write(word, one) ,因此这里的每个 val.get()返回值都是 1 , sum 就是最终的 key 的计数。由于 sum 是一个 int型,而 hadoop 的输入输出键值对不能是 java基本类型,必须是一个对象,所以需要用 result.set(sum) 实现类型转换,然后输出( key,result )。 (key, result) 键值对直接输出到了磁盘文件中,其输出路径在 main 函数中被指定。

Page 35: PageRank 的 MapReduce 实现

谢谢 谢谢