2021.11.19 MapReduce

一、今日学习内容

   今天完成了关于Mapreduce的实验,例:去重

实验目的

1.准确理解MapReduce去重的设计原理

2.熟练掌握MapReduce去重的程序编写

3.学会自己编写MapReduce去重代码解决实际问题

实验原理

数据去重主要是为了掌握和利用并行化思想来对数据进行有意义的筛选。统计大数据集上的数据种类个数、从网站日志中计算访问地等这些看似庞杂的任务都会涉及数据去重。

数据去重的最终目标是让原始数据中出现次数超过一次的数据在输出文件中只出现一次。在MapReduce流程中,map的输出<key,value>经过shuffle过程聚集成<key,value-list>后交给reduce。我们自然而然会想到将同一个数据的所有记录都交给一台reduce机器,无论这个数据出现多少次,只要在最终结果中输出一次就可以了。具体就是reduce的输入应该以数据作为key,而对value-list则没有要求(可以设置为空)。当reduce接收到一个<key,value-list>时就直接将输入的key复制到输出的key中,并将value设置成空值,然后输出<key,value>

MaprReduce去重流程如下图所示:

 

 

 

实验环境

Linux Ubuntu 14.04

jdk-7u75-linux-x64

hadoop-2.6.0-cdh5.4.5

hadoop-2.6.0-eclipse-cdh5.4.5.jar

eclipse-java-juno-SR2-linux-gtk-x86_64

实验内容

现有一个某电商网站的数据文件,名为buyer_favorite1,记录了用户收藏的商品以及收藏的日期,文件buyer_favorite1中包含(用户id,商品id,收藏日期)三个字段,数据内容以“\t”分割,由于数据很大,所以为了方便统计我们只截取它的一部分数据,内容如下:

  1. 用户id   商品id    收藏日期  
  2. 10181   1000481   2010-04-04 16:54:31  
  3. 20001   1001597   2010-04-07 15:07:52  
  4. 20001   1001560   2010-04-07 15:08:27  
  5. 20042   1001368   2010-04-08 08:20:30  
  6. 20067   1002061   2010-04-08 16:45:33  
  7. 20056   1003289   2010-04-12 10:50:55  
  8. 20056   1003290   2010-04-12 11:57:35  
  9. 20056   1003292   2010-04-12 12:05:29  
  10. 20054   1002420   2010-04-14 15:24:12  
  11. 20055   1001679   2010-04-14 19:46:04  
  12. 20054   1010675   2010-04-14 15:23:53  
  13. 20054   1002429   2010-04-14 17:52:45  
  14. 20076   1002427   2010-04-14 19:35:39  
  15. 20054   1003326   2010-04-20 12:54:44  
  16. 20056   1002420   2010-04-15 11:24:49  
  17. 20064   1002422   2010-04-15 11:35:54  
  18. 20056   1003066   2010-04-15 11:43:01  
  19. 20056   1003055   2010-04-15 11:43:06  
  20. 20056   1010183   2010-04-15 11:45:24  
  21. 20056   1002422   2010-04-15 11:45:49  
  22. 20056   1003100   2010-04-15 11:45:54  
  23. 20056   1003094   2010-04-15 11:45:57  
  24. 20056   1003064   2010-04-15 11:46:04  
  25. 20056   1010178   2010-04-15 16:15:20  
  26. 20076   1003101   2010-04-15 16:37:27  
  27. 20076   1003103   2010-04-15 16:37:05  
  28. 20076   1003100   2010-04-15 16:37:18  
  29. 20076   1003066   2010-04-15 16:37:31  
  30. 20054   1003103   2010-04-15 16:40:14  
  31. 20054   1003100   2010-04-15 16:40:16  

要求用Java编写MapReduce程序,根据商品id进行去重,统计用户收藏商品中都有哪些商品被收藏。结果数据如下:

  1. 商品id  
  2. 1000481  
  3. 1001368  
  4. 1001560  
  5. 1001597  
  6. 1001679  
  7. 1002061  
  8. 1002420  
  9. 1002422  
  10. 1002427  
  11. 1002429  
  12. 1003055  
  13. 1003064  
  14. 1003066  
  15. 1003094  
  16. 1003100  
  17. 1003101  
  18. 1003103  
  19. 1003289  
  20. 1003290  
  21. 1003292  
  22. 1003326  
  23. 1010178  
  24. 1010183  
  25. 1010675  

实验步骤

1.切换到/apps/hadoop/sbin目录下,开启Hadoop

  1. cd /apps/hadoop/sbin  
  2. ./start-all.sh  

2.Linux本地新建/data/mapreduce2目录。

  1. mkdir -p /data/mapreduce2  

3. (自行生成文本文件,放到个人指定文件夹下)Linux中切换到/data/mapreduce2目录下,用wget命令从http://192.168.1.100:60000/allfiles/mapreduce2/buyer_favorite1网址上下载文本文件buyer_favorite1

  1. cd /data/mapreduce2  
  2. wget http://192.168.1.100:60000/allfiles/mapreduce2/buyer_favorite1  

然后在当前目录下用wget命令从http://192.168.1.100:60000/allfiles/mapreduce2/hadoop2lib.tar.gz网址上下载项目用到的依赖包。

  1. wget http://192.168.1.100:60000/allfiles/mapreduce2/hadoop2lib.tar.gz  

hadoop2lib.tar.gz解压到当前目录下。

  1. tar zxvf hadoop2lib.tar.gz  

4.首先在HDFS上新建/mymapreduce2/in目录,然后将Linux本地/data/mapreduce2目录下的buyer_favorite1文件导入到HDFS/mymapreduce2/in目录中。

  1. hadoop fs -mkdir -p /mymapreduce2/in  
  2. hadoop fs -put /data/mapreduce2/buyer_favorite1 /mymapreduce2/in  
  3. 新建maven项目,项目名为mapreduce2

导入依赖

 

6.编写程序代码,并描述其思路

数据去重的目的是让原始数据中出现次数超过一次的数据在输出文件中只出现一次。我们自然想到将相同key值的所有value记录交到一台reduce机器,让其无论这个数据出现多少次,最终结果只输出一次。具体就是reduce的输出应该以数据作为key,而对value-list没有要求,当reduce接收到一个时,就直接将key复制到输出的key中,将value设置为空。

Map代码

  1. public static class Map extends Mapper<Object , Text , Text , NullWritable>  
  2. //map将输入中的value复制到输出数据的key上,并直接输出  
  3. {  
  4. private static Text newKey=new Text();      //从输入中得到的每行的数据的类型  
  5. public void map(Object key,Text value,Context context) throws IOException, InterruptedException  
  6. //实现map函数  
  7. {             //获取并输出每一次的处理过程  
  8. String line=value.toString();  
  9. System.out.println(line);  
  10. String arr[]=line.split("\t");  
  11. newKey.set(arr[1]);  
  12. context.write(newKey, NullWritable.get());  
  13. System.out.println(newKey);  
  14. }  
  15. }  

map阶段采用Hadoop的默认的作业输入方式,把输入的valuesplit()方法截取,截取出的商品id字段设置为key,设置value为空,然后直接输出<key,value>

reduce端代码

  1. public static class Reduce extends Reducer<Text, NullWritable, Text, NullWritable>{  
  2. public void reduce(Text key,Iterable<NullWritable> values,Context context) throws IOException, InterruptedException  
  3. //实现reduce函数  
  4. {  
  5. context.write(key,NullWritable.get());   //获取并输出每一次的处理过程  
  6. }  
  7. }  

map输出的<key,value>键值对经过shuffle过程,聚成<key,value-list>后,会交给reduce函数。reduce函数,不管每个key 有多少个value,它直接将输入的赋值给输出的key,将输出的value设置为空,然后输出<key,value>就可以了。

完整代码

 

package mapreduce;  
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.NullWritable;  
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.input.TextInputFormat;  
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;  
import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;  
public class Filter{  
public static class Map extends Mapper<Object , Text , Text , NullWritable>{  
private static Text newKey=new Text();  
public void map(Object key,Text value,Context context) throws IOException, InterruptedException{  
String line=value.toString();  
System.out.println(line);  
String arr[]=line.split("\t");  
newKey.set(arr[1]);  
context.write(newKey, NullWritable.get());  
System.out.println(newKey);  
}  
}  
public static class Reduce extends Reducer<Text, NullWritable, Text, NullWritable>{  
public void reduce(Text key,Iterable<NullWritable> values,Context context) throws IOException, InterruptedException{  
context.write(key,NullWritable.get());  
}  
}  
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException{  
Configuration conf=new Configuration();  
System.out.println("start");  
Job job =new Job(conf,"filter");  
job.setJarByClass(Filter.class);  
job.setMapperClass(Map.class);  
job.setReducerClass(Reduce.class);  
job.setOutputKeyClass(Text.class);  
job.setOutputValueClass(NullWritable.class);  
job.setInputFormatClass(TextInputFormat.class);  
job.setOutputFormatClass(TextOutputFormat.class);  
Path in=new Path("hdfs://localhost:9000/mymapreduce2/in/buyer_favorite1");  
Path out=new Path("hdfs://localhost:9000/mymapreduce2/out");  
FileInputFormat.addInputPath(job,in);  
FileOutputFormat.setOutputPath(job,out);  
System.exit(job.waitForCompletion(true) ? 0 : 1);  
}  
}  

 

 

 

7.待执行完毕后,进入命令模式下,在HDFS/mymapreduce2/out查看实验结果。

  1. hadoop fs -ls /mymapreduce2/out  
  2. hadoop fs -cat /mymapreduce2/out/part-r-00000  

 

 

 

 

 

 

 

 

 

 

 

   其他实验类似

posted @ 2021-11-19 20:02  小仙女W  阅读(62)  评论(0编辑  收藏  举报