前面我们介绍了Hadoop的分布式文件系统HDFS,解决的是大数据的存储问题。那么,对于HDFS上的存储的海量数据,应该怎么计算呢?这就要用到了Google在PageRank(页面排名)问题中使用的MapReduce编程模型。本节就来详细讨论一下MapReduce编程模型的基本原理。
1.PageRank的基本原理
在我们使用搜索引擎检索某个内容时,往往会得到很多匹配的网页结果。这些网页该以何种顺序呈现给用户,这就要考虑PageRank问题了(当然这里我们不考虑竞价因素)。假设有四个网页,它们之间的关系如下图所示。箭头表示前一个网页指向后一个网页。
上图的左边表示四个网页之间的指向关系。右边是这个四个网页之间的状态转移矩阵,简言之,横轴的网页如果指向了纵轴的网页,交叉位置就是1,否则是0。最后一行的Rank表示每个网页的得分,即每一列的和。得分越高的网页,排名越靠前,优先展示给用户。这就是PageRank的基本原理。
上图只列出了四个网页的排名,4乘4的状态转移矩阵当然一台计算就能轻松搞定。但是Google每天从全世界爬取回来的网页数量在十亿甚至百亿数量级,此时的状态转移矩阵就不是一台或者几台计算机能处理了的。这就要用到MapReduce编程模型来处理。如上图将一个大的矩阵分成四个小的矩阵,分给不同的计算机来处理,然后将结果汇总。这种分而治之的思想就是MapReduce。
2.MapReduce编程模型
MapReduce是一种分治思想,即将一个大任务分割乘若干个小任务,然后逐一解决这些小任务,最后将所有小任务的结果合并起来,即得到原来大任务的结果。我们通过下图的例子来说明这个过程。
假设我们现在有一个求和的任务,计算1到10的和。Map阶段先将任务分割,最好按照负载均衡的原则来划分,这样不至于发生数据倾斜(就是很多个数据量小的任务很快就结束了,然后大家一起等一个数据量特别大的任务在执行)。这里平均分割成3个小任务,然后交给3个Map进程来求和。最后将3个Map计算的结果输入给Reduce进程进行汇总,即可得到最终的结果。这就是MapReduce编程模型的基本思想。
MapReduce编程模型需要注意以下几个方面的问题:
(1)Map的输入源可以是本地磁盘,HDFS,Hive,HBase等;Map的输出是Reduce的输入;Reduce的输出源可以是本地磁盘,HDFS,Hive,HBase等。
(2)Map和Reduce的输入和输出都是<key, value>的形式:<k1, v1>代表Map的输入;<k2, v2>代表Map的输出;<k3, v3>代表Reduce的输入;<k4, v4>代表Reduce的输出。
(3)k2 = k3, v3 = [v2]:由于相同的key都由同一个Reduce进程处理,这就导致了来自不同Map进程的相同的key的value汇聚成一个向量[v2]作为v3。
(4)所有的数据类型必须是Hadoop自己的数据类型:如字符串Text;整型IntWritable;长整型LongWritable;双精度浮点型DoubleWritable;空类型NullWritable等等。
(5)Java序列化后的类对象可以作为输入和输出的对象;类似的,Hadoop序列化后的类对象可以作为Map和Reduce的输入和输出。
(6)MapReduce编程模型至少应该有三个Java class:job.class = map.class + reduce.class
3.演示wordcount例子
(1)在HDFS上创建输入目录/input:
[root@bigdata112 ~]# hdfs dfs -mkdir /input
(2)将本地数据文件data.txt上传至该目录:
[root@bigdata112 ~]# hdfs dfs -put /root/input/data.txt /input
[root@bigdata112 ~]# hdfs dfs -ls /input
Found 1 items
-rw-r--r-- 1 root supergroup 60 2018-04-09 22:39 /input/data.txt[root@bigdata112 ~]# hdfs dfs -cat /input/data.txt
I love Beijing
I love China
Beijing is the capital of China
(3)进入到Hadoop的示例程序目录:
[root@bigdata112 ~]# cd trainings/hadoop-2.4.1/share/hadoop/mapreduce/
[root@bigdata112 mapreduce]# pwd
/root/trainings/hadoop-2.4.1/share/hadoop/mapreduce
(4)执行示例程序中的Wordcount程序,以HDFS上的/input/data.txt作为输入数据,输出结果存放到HDFS上的/out/wc目录下:
[root@bigdata112 mapreduce]# hadoop jar hadoop-mapreduce-examples-2.4.1.jar \
wordcount /input/data.txt /output/wc
(5)查看进度和结果:
可以通过终端打印出来的日志信息知道执行进度:
18/04/09 22:47:44 INFO mapreduce.Job: map 0% reduce 0%
18/04/09 22:48:21 INFO mapreduce.Job: map 100% reduce 0%
18/04/09 22:48:39 INFO mapreduce.Job: map 100% reduce 100%
执行结束后可以在HDFS上的/out/wc目录下查看是否有_SUCCESS标志文件来判断是否执行成功。
[root@bigdata112 mapreduce]# hdfs dfs -ls /output/wc
Found 2 items
-rw-r--r-- 1 root supergroup 0 2018-04-09 22:48 /output/wc/_SUCCESS
-rw-r--r-- 1 root supergroup 55 2018-04-09 22:48 /output/wc/part-r-00000
如果执行成功,可以在part-r-00000文件中查看到wordcount程序的结果。
[root@bigdata112 mapreduce]# hdfs dfs -cat /output/wc/part-r-00000
Beijing 2
China 2
I 2
capital 1
is 1
love 2
of 1
the 1
至此,我们简单讨论了Hadoop的MapReduce编程模型的原理,以后我们会演示MapReduce程序的详细开发过程。祝你玩的愉快!