实验三十 MapReduce与Spark读写Redis

9 篇文章 1 订阅
7 篇文章 0 订阅

实验指导:

30.1 实验目的

1.会使用MapReduce访问Redis数据;

2.会使用Spark访问Redis数据。

30.2 实验要求

1.在master机上,使用MapReduce代码读取Redis数据;

2.在master机上,使用Spark代码读取Redis数据。

30.3 实验原理

假定现有一个大为1000G的大表big.txt和一个大小为10G的小表small.txt,请基于MapReduce思想编程实现判断小表中单词在大表中出现次数。也即所谓的“扫描大表、加载小表”。

为解决上述问题,可开启10个Map。这样,每个Map只需处理总量的1/10,将大大加快处理。而在单独Map内,由于10G的small.txt依旧非常巨大,显然不适宜HashSet加载到内存等措施,此时可借助第三方存储介质(如Redis),在Map阶段先加载部分数据,然后再加载部分数据,甚至,可直接将结果写入Redis如图30-1所示。

图30-1 Map阶段访问Redis

30.4 实验步骤

主要包括MapReduce读取Redis代码和Spark读取Redis数据代码。

30.4.1 MapReduce读取Redis

首先是准备数据阶段,即准备好big.txt并将其上传至HDFS,准备好待查城市名并将其导入Redis。接着为编程阶段,即编写MapReduce程序,在此程序Map阶段,取出Redis里待查城市,顺序扫描数据块里数据,是该城市则输出,不是则不做任何操作。最后,在集群上执行该程序。

30.4.1.1 准备HDFS数据

首先,登录master机或者master机器,确认该机上存在“/root/data/30/big.txt”(如果不存在请自己手动添加这样的文本数据),如图30-2所示。

图30-2 确认本地文件big.txt

接着,登录到master机或者master机器上,查看HDFS里是否已存在目录“/user/root/redis/in”,若不存在,使用下述命令新建该目录。

[root@master ~]# /usr/cstor/hadoop/bin/hdfs  dfs  -mkdir  -p  /user/root/redis/in

最后,使用下述命令将master机本地文件“/root/data/30/big.txt”上传至HDFS的“/user/root/redis/in”目录:

[root@master ~]# /usr/cstor/hadoop/bin/hdfs  dfs  -put  /root/data/30/big.txt  /user/root/redis/in

最后,请进入HDFS Web页面,确认HDFS上文件与内容,如图30-3所示。

图30-3 确认HDFS上big.txt文件位置与内容

也可以使用命令行查看文件:

[root@master ~]# /usr/cstor/hadoop/bin/hdfs  dfs  -ls  /user/root/redis/in

30.4.1.2 准备Redis数据

首先,参考下述命令登录到redis数据库:

进入redis的src目录:cd /usr/cstor/redis/src

然后登陆redis

[root@master ~]# redis-cli  -h 10.1.1.36(这里是运行redis服务器的主机的ip)

接着,向Redis数据库里写入,参考命令如下:

10.1.1.36:6379> set  city  nanjing
10.1.1.36:6379> get  city

30.4.1.3 编程MapReduce程序

首先,打开Eclipse,依次点击“FileNewOther…Map/Reduce Project”,在弹出的“New MapReduce Project Wizard”对话框中,“Project name:”一栏填写项目名“SharedLargeMemory”,然后直接点击该对话框的“Finish”按钮。

接着,新建LargeMemory类并指定包名(代码中为cn.cstor.redis),在LargeMemory.java文件中,依次写入如下代码:

package cn.cstor.redis;
import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import redis.clients.jedis.Jedis;

public class LargeMemory {
public static class TokenizerMapper extends Mapper<Object, Text, Text, IntWritable> {
private final static IntWritable one = new IntWritable(1);
Jedis jedis = null;
protected void setup(Context context) throws IOException, InterruptedException {
jedis = new Jedis(context.getConfiguration().get("redisIP"));
System.out.println("setup ok *^_^* ");
}
public void map(Object key, Text value, Context context) throws IOException, InterruptedException {
String[] values = value.toString().split(" ");
for (int i = 0; i < values.length; i++) {
if (jedis.get("city").equals(values[i])) {
context.write(new Text(values[i]), one);
}
}
}
}
public static class IntSumReducer extends Reducer<Text, IntWritable, Text, IntWritable> {
private IntWritable result = new IntWritable();
public void reduce(Text key, Iterable<IntWritable> values, Context context)
throws IOException, InterruptedException {
int sum = 0;
for (IntWritable val : values) {
sum += val.get();
}
result.set(sum);
context.write(key, result);
}
}
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
conf.set("redisIP", args[0]);
Job job = Job.getInstance(conf, "RedisDemo");
job.setJarByClass(LargeMemory.class);
job.setMapperClass(TokenizerMapper.class);
job.setReducerClass(IntSumReducer.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
FileInputFormat.addInputPath(job, new Path(args[1]));
FileOutputFormat.setOutputPath(job, new Path(args[2]));
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
}

由于该程序依赖Redis,故,还需添加Redis客户端Jar包。实际操作时,选中该项目,“NewFolder”,在弹出的对话框中填写“lib”,接着将“jedis-2.1.0.jar”(这个jedis-2.1.0.jar包如果实验环境下找不到可以从网络上下载也是同样可以使用的) 复制到该文件夹(“lib”)下,最后,选中“jedis-2.1.0.jar”,依次点击“Build PathAdd to Build Path”完成添加依赖包,如图30-4所示。

图30-4 将Jar包添加到Build Path

至此,已完成代码开发,图30-5为本项目结构图,请读者对照该图,分析项目结构图中各模块。

图30-5 本项目集成开发界面

30.4.1.4 打包该程序

待代码编写结束,选中该项目,依次点击“ExportJavaJAR file”,弹出对话框,在图30-6中填写打包位置,接着Finish即可。笔者此处打包时包名及其位置为“C:\Users\allen\Desktop\SharedLargeMemory.jar”。

图30-6 项目打包

30.4.1.5 执行代码

首先,使用xftp或者一体机提供的工具将“C:\Users\allen\Desktop\SharedLargeMemory.jar”上传至master机,此处上传至“/root/SharedLargeMemory.jar”。

接着,登录master机上,使用下述命令提交SharedLargeMemory.jar任务。

[root@master ~]# /usr/cstor/hadoop/bin/hadoop  jar  /root/SharedLargeMemory.jar \
cn.cstor.redis.LargeMemory  10.1.1.36  /user/root/redis/in/big.txt  /user/root/redis/SLMResult

30.4.2 Spark读取Redis

和MapReduce相比,使用Spark读写Redis则简单的多,首先登录Redis准备数据;接着,在启动Spark时指定Redis包;最后,在Spark交互式执行界面中直接编写代码访问Redis即可。具体操作如下:

30.4.2.1 准备Redis数据

登录Redis,向redis数据库添加数据

[root@master ~]$ redis-cli  -h  client
172.17.0.15:6379> SET  chengshi sh,bj,sz,nj,hf
172.17.0.15:6379> get  chengshi

30.4.2.2 启动SparkShell

首先启动Spark集群,再启动SparkShell,由于Spark访问Redis时需要Redis客户端jedis,故此处启动Spark时需指定jedis包(如果redis的jar包不存在,可以手动放到/usr/cstor/redis/这个目录下),启动命令如下:

[root@master ~]$/usr/cstor/spark/bin/spark-shell --master spark://master:7077 --jars /usr/cstor/redis/jedis-2.1.0.jar

启动成功如下:

图30-7 启动成功

30.4.2.3 编写访问代码

在交互代码中连接Redis(注意redis的IP地址修改成自己的),读者可按下述命令操作:

scala> import redis.clients.jedis.Jedis
import redis.clients.jedis.Jedis
scala> var jd=new Jedis("172.17.0.15",6379)
jd: redis.clients.jedis.Jedis = redis.clients.jedis.Jedis@7dae9ff4
scala> var str=jd.get("chengshi")
str: String = sh,bj,sz,nj,hf
scala> var strList=str.split(",")
strList: Array[String] = Array(sh, bj, sz, nj, hf)
scala> val a = sc.parallelize(strList, 3)
a: org.apache.spark.rdd.RDD[String] = ParallelCollectionRDD[0] at parallelize at <console>:28
scala> val b = a.keyBy(_.length)
b: org.apache.spark.rdd.RDD[(Int, String)] = MapPartitionsRDD[1] at keyBy at <console>:30
scala> b.collect
res0: Array[(Int, String)] = Array((2,sh), (2,bj), (2,sz), (2,nj), (2,hf))

30.5 实验结果

30.5.1 MapReduce读取Redis实验

图30-8

30.5.2 Spark读取Redis实验

图30-9

实验操作:

步骤1:搭建Spark集群

配置Spark集群(独立模式):

前提:1、请自行配置各节点之间的免密登录,并在/etc/hosts中写好hostname与IP的对应,这样方便配置文件的相互拷贝。2、因为下面实验涉及Spark集群使用HDFS,所以按照之前的实验预先部署好HDFS。

在master机上操作:确定存在spark。

[root@master ~]# ls /usr/cstor
spark/
[root@master ~]#

在master机上操作:进入/usr/cstor目录中。

[root@master ~]# cd /usr/cstor
[root@master cstor]#

进入配置文件目录/usr/cstor/spark/conf, 先拷贝并修改slave.templae为slave。

[root@master ~]# cd /usr/cstor/spark/conf
[root@master cstor]# cp  slaves.template slaves

然后用vim命令编辑器编辑slaves文件

[root@master cstor]# vim slaves

编辑slaves文件将下述内容添加到slaves文件中。

slave1
slave2
slave3

上述内容表示当前的Spark集群共有三台slave机,这三台机器的机器名称分别是slave1~3。

在spark-conf.sh中加入JAVA_HOME。

[root@master cstor]# vim /usr/cstor/spark/sbin/spark-config.sh

加入以下内容

export JAVA_HOME=/usr/local/jdk1.7.0_79

将配置好的Spark拷贝至slaveX、client。(machines在目录/root/data/2下,如果不存在则自己新建一个)

使用for循环语句完成多机拷贝。

[root@master ~]# cd /root/data/2
[root@master ~]# cat  machines
slave1
slave2
slave3
client
[root@master ~]# for  x  in  `cat  machines` ; do  echo  $x ; scp  -r  /usr/cstor/spark/  $x:/usr/cstor/; done;

在master机上操作:启动Spark集群。

[root@master local]# /usr/cstor/spark/sbin/start-all.sh

配置HDFS:

配置Spark集群使用HDFS:

首先关闭集群(在master上执行)

[root@master ~]# /usr/cstor/spark/sbin/stop-all.sh

将Spark环境变量模板复制成环境变量文件。

[root@master ~]# cd /usr/cstor/spark/conf
[root@master conf]# cp spark-env.sh.template spark-env.sh

修改Spark环境变量配置文件spark-env.sh。

[root@master conf]$ vim spark-env.sh

在sprak-env.sh配置文件中添加下列内容。

export HADOOP_CONF_DIR=/usr/cstor/hadoop/etc/hadoop

重新启动spark

[root@master local]# /usr/cstor/spark/sbin/start-all.sh

步骤2:启动redis

步骤2:启动redis(此处博主是以客户端作为Redis服务器进行存储,使用master进行远程访问)

步骤3:向redis中加入数据

步骤4:上传数据文件至HDFS

步骤5:编写MapReduce程序

 

步骤6:打包程序

 

步骤7:运行程序

博主在此处曾多次出现报错,原因有以下几点:

1.程序引入的JAR包(jedis-2.1.0.jar)以外部引入方式引入,没有拷贝到项目里,导致在将项目打成jar包时,未包含进去;

2.数据未上传到HDFS上,出现找不到输入数据源;

3.在出现上述两种问题后,已经多次执行了运行程序命令,导致在HDFS中已经生成了数据输出路径,再次执行下述运行程序命令则会出现报错,解决方法是删除已经存在的输出路径([root@master ~]# /usr/cstor/hadoop/bin/hdfs  dfs  -rm -R    /user/root/redis/SLMResult)后再次执行运行程序命令即可。

先把出现的问题扔出来大家提前准备跳坑:

下面是无措操作,可以用来验证:

步骤8:启动Spark-shell

步骤9:编写redis访问代码

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值