7.2 RHadoop安装与使用

问题

R如何连接Hadoop?

引言

RHadoop产品第一次实现了R语言与Hadoop的结合,进行海量数据分析。Hadoop主要用来存储海量数据,R语言完成MapReduce算法,用来替代Java的MapReduce实现。有了RHadoop可以让广大的R语言爱好者,有更强大的工具处理大数据, 10G、100G、TB、PB,由于大数据所带来的单机性能问题可能会一去不复返了。但对于单独的R语言使用者、Java使用者或者Hadoop使用者来说,同时具备三种知识并不容易。

7.2.1 环境准备

首先是环境准备,这里我选择了Linux Ubuntu操作系统12.04的64位版本,大家可以根据自己的使用习惯选择顺手的Linux。

Java(JDK)一定要用Oracle SUN官方的版本,请从官网下载 ( http://www.oracle.com/technetwork/java/javase/downloads/index.html )。 Linux Ubuntu操作系统的自带的OpenJDK会有各种不兼容。JDK请选择1.6.x的版本,JDK1.7版本也可能会有不兼容情况。R语言环境 请安装R 2.15.3版本,R 2.14版本和R 3.0以上版本不能够兼容RHadoop。本节使用的系统环境是:

  • Linux Ubuntu 12.04.2 LTS 64bit server
  • R 2.15.3 64bit
  • Java JDK 1.6.x
  • Hadoop 1.1.2
  • IP: 192.168.1.243

RHadoop只支持Linux系统环境。关于Hadoop的安装和配置,请参考附录F。

7.2.2 RHadoop安装

RHadoop项目包含三个R包(rmr、hdfs和rhbase),由于这三个库不能在CRAN中找到,所以需要自己下载。

1. 下载RHadoop相关的3个程序包

这三个程序包是rmr-2.1.0、rhdfs-1.0.5和rhbase-1.1,下载地址为 https://github.com/RevolutionAnalytics/RHadoop/wiki/Downloads。虽然RHadoop已经推出Windows版本的rhdfs和rmr2,但作为Hadoop的应用,还是建议大家使用Linux。

2. RHadoop的安装,建议使用root权限操作

~ sudo –I  # 切换到root用户
~ whoami
root
~ mv  rmr-2.1.0.tar.gz /root/R  # 复制程序包到目录/root/R
~ mv  rhdfs-1.0.5.tar.gz /root/R
~ mv  rhbase-1.1.tar.gz /root/R

接下来,我们需要先安装这三个库的依赖库。

3. 安装依赖库

由于RHadoop项目依赖于Java的环境,所以我们先要安装rJava,在4.3节我们已经安装过了rJava,这里不多解释。

~ R CMD javareconf  # 在R运行环境中配置Java的环境变量
~ R  # 启动R程序
> install.packages("rJava")  # 安装rJava包

然后,还要安装其他的几个依赖库,reshape2、Rcpp、iterators、itertools、digest、RJSONIO、functional,通过install.packages()函数都可以直接安装。

> install.packages("reshape2")
> install.packages("Rcpp")
> install.packages("iterators")
> install.packages("itertools")
> install.packages("digest")
> install.packages("RJSONIO")
> install.packages("functional")

4. 安装rhdfs库

接下来安装rhdfs库,在环境变量中增加 HADOOP_CMD 和 HADOOP_STREAMING 两个变量,可以用export在当前命令窗口中增加。但为下次方便使用,最好把变量增加到系统环境变量 /etc/environment 文件中。再用R CMD INSTALL命令安装rhdfs包就可以顺利完成了。

在当前运行环境中,设置环境变量。

~ export HADOOP_CMD=/root/hadoop/hadoop-1.1.2/bin/hadoop
~ export HADOOP_STREAMING=/root/hadoop/hadoop-1.1.2/contrib/streaming/hadoop-streaming-1.1.2.jar

把环境变量写到 /etc/environmen 文件。

~ sudo vi /etc/environment
HADOOP_CMD=/root/hadoop/hadoop-1.1.2/bin/hadoop
HADOOP_STREAMING=/root/hadoop/hadoop-1.1.2/contrib/streaming/hadoop-streaming-1.1.2.jar
~ . /etc/environment   # 让环境变量生效
~ R CMD INSTALL /root/R/rhdfs_1.0.5.tar.gz  # 安装rhdfs库

5. 安装rmr库

安装rmr库,使用R CMD INSTALL 命令就可以顺利完成了。

~  R CMD INSTALL rmr2_2.1.0.tar.gz

6. 安装rhbase库

安装rhbase库,会在7.5节介绍,这里暂时跳过。

7. 列出所有的安装包

最后,我们可以查看一下,RHADOOP都安装了哪些库。

~ ls /disk1/system/usr/local/lib/R/site-library/
digest  functional  iterators  itertools  plyr  Rcpp  reshape2  rhdfs  rJava  RJSONIO  rmr2  stringr

由于我的硬盘是外接的,使用mount和软连接(ln -s)挂载了R类库的目录,所以是R的类库在/disk1/system 目录下。一般R的类库目录是/usr/lib/R/site-library 或者 /usr/local/lib/R/site-library,用户也可以使用 whereis R 的命令查询自己电脑上R类库的安装位置。

7.2.3 RHadoop程序开发

安装好rhdfs和rmr2两个包后,我们就可以使用R尝试一下Hadoop的操作了。

1. rhdfs包的基本操作

rhdfs包的使用。

> library(rhdfs)  # 加载rhdfs包
Loading required package: rJava
HADOOP_CMD=/root/hadoop/hadoop-1.1.2/bin/hadoop
Be sure to run hdfs.init()
> hdfs.init()  # 初始化R与Hadoop建立连接

对比Hadoop命令和RHadoop函数的操作。

(1) 查看hdfs文件目录

  • hadoop的命令:hadoop fs -ls /user
  • R语言函数:hdfs.ls("/user/")

用Hadoop命令查看hadoop目录

~ hadoop fs -ls /user

Found 4 items
drwxr-xr-x   - root supergroup          0 2013-02-01 12:15 /user/conan
drwxr-xr-x   - root supergroup          0 2013-03-06 17:24 /user/hdfs
drwxr-xr-x   - root supergroup          0 2013-02-26 16:51 /user/hive
drwxr-xr-x   - root supergroup          0 2013-03-06 17:21 /user/root

rhdfs函数查看hadoop目录

> hdfs.ls("/user/")
  permission owner      group size          modtime        file
1 drwxr-xr-x  root supergroup    0 2013-02-01 12:15 /user/conan
2 drwxr-xr-x  root supergroup    0 2013-03-06 17:24  /user/hdfs
3 drwxr-xr-x  root supergroup    0 2013-02-26 16:51  /user/hive
4 drwxr-xr-x  root supergroup    0 2013-03-06 17:21  /user/root

(2) 查看hadoop数据文件

  • hadoop的命令:hadoop fs -cat /user/hdfs/o_same_school/part-m-00000
  • R语言函数:hdfs.cat("/user/hdfs/o_same_school/part-m-00000″)

用Hadoop命令查看hadoop数据文件

~ hadoop fs -cat /user/hdfs/o_same_school/part-m-00000
10,3,tsinghua university,2004-05-26 15:21:00.0
23,4007,北京第一七一中学,2004-05-31 06:51:53.0
51,4016,大连理工大学,2004-05-27 09:38:31.0
89,4017,Amherst College,2004-06-01 16:18:56.0
92,4017,斯坦福大学,2012-11-28 10:33:25.0
99,4017,Stanford University Graduate School of Business,2013-02-19 12:17:15.0

通过rhdfs函数查看hadoop数据文件

>  hdfs.cat("/user/hdfs/o_same_school/part-m-00000")
 [1] "10,3,tsinghua university,2004-05-26 15:21:00.0"
 [2] "23,4007,北京第一七一中学,2004-05-31 06:51:53.0"
 [3] "51,4016,大连理工大学,2004-05-27 09:38:31.0"
 [4] "89,4017,Amherst College,2004-06-01 16:18:56.0"
 [5] "92,4017,斯坦福大学,2012-11-28 10:33:25.0"
 [6] "99,4017,Stanford University Graduate School of Business,2013-02-19 12:17:15.0"

2. rmr算法的任务

下面介绍rmr2包的使用,同时比较普通的R程序与基于Hadoop的R程序。

> library(rmr2)  # 加载rmr2包
Loading required package: Rcpp
Loading required package: RJSONIO
Loading required package: digest
Loading required package: functional
Loading required package: stringr
Loading required package: plyr
Loading required package: reshape2

普通的R语言程序:

> small.ints = 1:10
> sapply(small.ints, function(x) x^2)
[1]   1   4   9  16  25  36  49  64  81 100

基于Hadoop的R语言程序:

> small.ints = to.dfs(1:10)
13/03/07 12:12:55 INFO util.NativeCodeLoader: Loaded the native-hadoop library
13/03/07 12:12:55 INFO zlib.ZlibFactory: Successfully loaded & initialized native-zlib library
13/03/07 12:12:55 INFO compress.CodecPool: Got brand-new compressor

> mapreduce(input = small.ints, map = function(k, v) cbind(v, v^2))  # 执行Map任务

packageJobJar: [/tmp/RtmpWnzxl4/rmr-local-env5deb2b300d03, /tmp/RtmpWnzxl4/rmr-global-env5deb398a522b, /tmp/RtmpWnzxl4/rmr-streaming-map5deb1552172d, /root/hadoop/tmp/hadoop-unjar7838617732558795635/] [] /tmp/streamjob4380275136001813619.jar tmpDir=null

13/03/07 12:12:59 INFO mapred.FileInputFormat: Total input paths to process : 1
13/03/07 12:12:59 INFO streaming.StreamJob: getLocalDirs(): [/root/hadoop/tmp/mapred/local]
13/03/07 12:12:59 INFO streaming.StreamJob: Running job: job_201302261738_0293
13/03/07 12:12:59 INFO streaming.StreamJob: To kill this job, run:
13/03/07 12:12:59 INFO streaming.StreamJob: /disk1/hadoop/hadoop-1.1.2/libexec/../bin/hadoop job  -Dmapred.job.tracker=hdfs://192.168.1.243:9001 -kill job_201302261738_0293
13/03/07 12:12:59 INFO streaming.StreamJob: Tracking URL: http://192.168.1.243:50030/jobdetails.jsp?jobid=job_201302261738_0293
13/03/07 12:13:00 INFO streaming.StreamJob:  map 0%  reduce 0%
13/03/07 12:13:15 INFO streaming.StreamJob:  map 100%  reduce 0%
13/03/07 12:13:21 INFO streaming.StreamJob:  map 100%  reduce 100%
13/03/07 12:13:21 INFO streaming.StreamJob: Job complete: job_201302261738_0293
13/03/07 12:13:21 INFO streaming.StreamJob: Output: /tmp/RtmpWnzxl4/file5deb791fcbd5

> from.dfs("/tmp/RtmpWnzxl4/file5deb791fcbd5")  # 查看hdfs输出的结果
$key
NULL
$val

       v
 [1,]  1   1
 [2,]  2   4
 [3,]  3   9
 [4,]  4  16
 [5,]  5  25
 [6,]  6  36
 [7,]  7  49
 [8,]  8  64
 [9,]  9  81
[10,] 10 100

因为MapReduce只能访问HDFS文件系统,所以首先需要用to.dfs()函数把数据存储到HDFS文件系统里。

MapReduce的运算结果再用from.dfs()函数从HDFS文件系统中取出。

3. rmr算法的wordcount任务

用rmr2实现wordcount任务,对文件中的单词计数。

我在HDFS上提前放置了数据文件/user/hdfs/o_same_school/part-m-00000。实现基于MapReduce的wordcount()函数,执行wordcount()函数,最后用from.dfs()函数从HDFS中取得结果。

> input<- '/user/hdfs/o_same_school/part-m-00000'    # 定义Hadoop上数据文件的位置
> wordcount = function(input, output = NULL, pattern = " "){  # wordcount算法函数
    wc.map = function(., lines) {     # map函数
            keyval(unlist( strsplit( x = lines,split = pattern)),1)
    }

  wc.reduce =function(word, counts ) {   # reduce函数
            keyval(word, sum(counts))
    }

 mapreduce(input = input ,output = output, input.format = "text",    # mapreduce计算函数
        map = wc.map, reduce = wc.reduce,combine = T)
}
> wordcount(input)  # 执行wordcount任务
> from.dfs("/tmp/RtmpfZUFEa/file6cac626aa4a7")  # 查看hdfs输出的结果
$key
 [1] "-"
 [2] "04:42:37.0"
 [3] "06:51:53.0"
 [4] "07:10:24.0"
 [5] "09:38:31.0"
 [6] "10:33:25.0"
 [7] "10,3,tsinghua"
 [8] "10:42:10.0"
 [9] "113,4017,Stanford"
[10] "12:00:38.0"
 $val

[1] 1 2 1 2 1 1 1 4 1 1 这样,就完成了RHadoop的中rhdfs和rmr2包的安装与使用。虽然RHadoop配置起来有点麻烦,但看到R语言在现实MapReduce过程的精炼的代码,还是值得的。

results matching ""

    No results matching ""