Hadoop权威指南笔记2——第2章:关于MapReduce

第2章 关于MapReduce

​ MapReduce是一个并行的数据处理模型,作者将使用Java、Ruby和Python实现。

2.1 气象数据集

​ 作者收集了气象的数据集,用于进行MapReduce分析。

数据格式

0057
332130	# USAF weather station identifier
99999	#WBAN weather station identifier
19500101 # observation date
8300	#observation time
4
+51317	# latitude (degrees x 1000)
+028783	#longitude (degrees x 1000)
FM-12
+0171	# elevation (meters)
99999
v020
320	# wind direction (degrees)
1	# quality code
N
0072
1
00450	#sky ceiling height (rneters)
1	# quality code
C
N
010000	# visibility distance ( meters)
1	# quality code
N
9

从1901年到2001年,每一年都有一个目录。

例如:1999年对应文件夹就包含下面的数据

% ls raw/1998 | head
010010-99999-1990.gz
010014-99999-1990.gz
010015-99999-1990.gz
010016-99999-1990.gz
010017-99999-1990.gz
010030-99999-1990.gz
010040-99999-1990.gz
010080-99999-1990.gz
010100-99999-1990.gz

2.2 使用Unix工具来分析数据

​ 在数据集中,每年全球气温最高纪录是多少?

​ 作者先用Unix工具来分析,然后再用Hadoop进行对比

运行的结果为

1901	317
1902	244
1903	289
1904	256
1905	283

2.3 使用Hadoop来分析数据

​ 可以先用MapReduce,在本地完成小规模测试后,就可以将作业部署到集群上运行。

2.3.1 map和reudce

​ MapReduce任务分为两个阶段,分别是map阶段和reduce阶段。每个阶段都是以键值对作为输入和输出。

​ map阶段的输入是NCDC数据,以文本进行输入,key是每一行的偏移量,value是改行的具体数据。

0067011990999991950051507004.. .9999999N9+00001+99999999999.. 0043011990999991950051512004...9999999N9+00221+99999999999..
0043011990999991950051518004...9999999N9-00111+99999999999...
0043012650999991949032412004...0500001N9+01111+99999999999.. 0043012650999991949032418004...0500001N9+00781+99999999999...

​ key是每一行的偏移量,value是改行具体的值

(0,0067011990999991950051507004...9999999N9+00001+99999999999.. .)
(106,0043011990999991950051512004...9999999N9+00221+99999999999.. .)
(212,0043011990999991950051518004...9999999N9-00111+99999999999.. .)
(318,0043012650999991949032412004...0500001N9+01111+99999999999.. .)
(424,0043012650999991949032418004...0500001N9+00781+99999999999.. .)

​ map阶段提取出年份和气温两个字段。

(1950,0)
(1950,22)
(1950,-11)
(1949,111)
(1949,78)

​ 将数据变为如下格式后,发送给reduce阶段

(1949,[111,78])
(1950,[0,22,-11])

​ Reduce阶段:遍历后面的list列表,找到最大的值。

​ 得到如下结果

(1949,111)
(1950,22)

整个输入由下图表示

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Fp3c68gV-1627481872409)(Hadoop权威指南笔记1/1MapReduce执行流程.png)]

2.3.2 Java版本的MapReduce

Mapper类



public class MaxTemperatureMapper extends MapReduceBase 
    implements Mapper<LongWritable,Text,Text,IntWritable>{//LongWritable,Text 表示写入的key和value。而Text,IntWritable表示写出的key和value

    private static final int MISSING = 9999;
    
    //重写map方法
    @Override
    public void map(LongWritable key, Text value, Context context)
    	throws IOException,InterruptedException{
        
        String line = value.toString();//转换为字符串
        String year = line.substring(15,19);//年份在第15到19个字符
        int airTemperature;//存储气温
        if(line.charAt(87)=='+'){// +号不需要添加
            airTemperature = Integer.parseInt(line.substring(88,92));
        }else{
            airTemperature = Integer.parseInt(line.substring(97,92));
        }
        String quality = line.substring(92,93);
        if(airTemperature != MISSING && quality.matches("[01459]")){
            // 将键值对写入 reduce端
            context.write(new Text(year),new IntWritable(airTemperature));
        }   
    }
}

Reduce类

public class MaxTemperatureReducer extends Reducer<Text,IntWritable,Text,IntWritable>{
    @Override
    public void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException{
        
        int maxValue = Integer.MIN_VALUE;
        // reduce端接收的是一个迭代器。迭代器中保存着有相同key的value序列
        for(IntWritable value : values){
            maxValue = Math.max(maxValue,value.get());
        }
        context.write(key,new IntWritable(maxValue))
    }
    
    
}

负责运行MapReduce作业

public class MaxTemperature{
    
    public static void main(String[] args) throws Exception{
        if (args.length != 2){
            // 输入的参数必须是两个
            System.exit(-1);
        }
        
        Job job = new Job();//新建一个Job
        job.setJarByClass(MaxTemperature.class);//设置当前类为Job类
        job.setJobName("Max temperature");//名称
        
        //设置输入的路径
        FileInputFormat.addInputPath(job, new Path(args[0]));
        //设置输出路径
        FileInputFormat.setOutputPath(job,new Path(args[1]));
        
        //设置Mapper类
        job.setMapperClass(MaxTemperatureMapper.class);
       //设置Reduce类 
        job.setReducerClass(MaxTemperatureReducer.class);
        //设置输出的key
        job.setOutputKeyClass(Text.class);
        //设置输出的value
        job.setOutputValueClass(IntWritable.class);
        
        // 规范的退出代码。成功为1,失败为0
        System.exit(job.waitForCompletion(true)?0:1);
        
        
    } 
}
2.3.2.1 运行测试

​ 调用Hadoop命令,第一个参数是类名,Hadoop启动JVM虚拟机来运行该类。

2.4 横向扩展

​ 之前都只是在小规模的数据集上进行测试。

​ 现在要扩展到大数据集,通过添加机器,然后运行在HDFS上,用YARN来进行资源管理。

2.4.1 数据流

定义术语:

​ (1)MapReduce作业(job) 是一个执行的工作单元: 包括输入数据、MapReduce程序和配置信息。

​ (2)一个作业(job)分为若干任务(task),比如说map任务和reduce任务。每个任务运行在一个节点(机器)上,通过YARN进行调度。

分片:

​ (1)MapReduce将输入数据分为等长的小数据块,称为输入分片(input split)。多个分片构建一个map任务。

​ (2)如果分片太大和太小都不太好。合理的分片大小趋向于HDFS的块大小,默认是128M。

​ (3)分区设置为块大小后,这样一个分区就是一个块,就不需要用到网络传输。

数据本地化优化:

​ (1)为了解决带宽,map任务执行的数据就是当前机器上的数据。称为数据本地优化

​ (2)但是有一种非常特殊的情况:对于数据A,我要执行数据A的map任务,但是有A的机器全在工作(执行其他map任务)。那么只能找别的机器运行,就需要用到网络带宽。

map任务

​ (1)map任务将输入写入本地磁盘,而非HDFS

​ (2)因为map产生的是中间结果,中间完成后就删除,没必要放入HDFS

​ (3)map在发送给reduce之前,会进行排序

reduce任务

​ (1)reduce任务的输入来自mapper的输出,这就需要用到网络带宽

​ (2)将数据接收,经过处理后,存储到HDFS中。

​ (3)输出的HDFS块的存储规律:第一个存储在本地节点,第二个存储其他机架的节点。

​ (4)若有多个reduce任务,map就会将输出进行分区,为每个reduce任务建一个分区。

​ (5)分区:由若干个相同的的key组成,这些key就是map端的输出key。

​ (6)分区数可以用户自定义,默认是通过哈希数来分区,比较高效。

​ (7)多个map端 和 多个reduce端 之间的多分区传递方式,就称之为shuffle

没有reduce任务

​ (1)直接将map输出写入HDFS

2.4.2 Combiner函数

​ Map端传递给Reducer端需要用到网络带宽,这限制了速度。

​ 所以可以先 map => combiner => reducer。

​ combiner的工作过程和reduce类似,可以减轻reduce的任务。

例子

第一个map端的输出

(1950, 0)
(1950,20)
(1950,10)

第二个map端的输出

(1950,25)
(1950,15)

不使用combiner的 reducer 端的输入

(1950,[0,20,10,25,15])

不使用combiner的 reducer端的输出

(1950,25)

使用combiner的 reducer端的输入

(1950,[20,25])

使用combiner的 reducer端的输出

(1950,25)

用下列表达式来表示,两个map对于两个combiner,combiner执行max

max(0,20,10,25,15) = max(max(0,20,10),max(25,15)) = max(20,25) = 25

两个map对于两个combiner,combiner执行mean。显然这个结果是错的,所以combiner并不能替代Reducer,只是一个辅助工具。

mean(mean(0,20,10),mean(25,15)) = mean(10,20)= 15

指定一个Combiner

public class MaxTemperatureWithCombiner{
    public static void main(String[] args) throws Exception{
        if(args.length !=2){
            // 退出程序
            System.exit(-1);
        }
        
        Job job = new Job();
        job.setJarByClass(MaxTemperatureWithCombiner.class);
        job.setJobName("Max temperature");
        
        FileInputFormat.addInputPath(job,new Path(args[0]));
        FileOutputFormat.setOutputPath(job,new Path(args[1]));
        
        job.setMapperClass(MaxTemperatureMapper.class);
       	//设置一个combiner
        job.setCombinerClass(MaxTemperatureReducer.class);
        job.setReducerClass(MaxTemperatureReducer.class);
        
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);
        
        // 规范的退出代码。成功为1,失败为0
        System.exit(job.waitForCompletion(true)?0:1);
    }
    
}

2.4.3 运行分布式的MapReduce作业

​ 该程序可以直接在集群上运行

​ 将在第6章分析在集群上运行程序的机制

2.5 Hadoop Streaming

​ Hadoop除了运行Java之外,还允许Ruby和Python等语言。

​ Streaming适合文本处理,输入是偏移量,文本。输出是年份,最高气温。

2.5.1 Ruby版本

​ pass

2.5.1 Python版本

​ 作者使用的是Python2,现在以及普及Python3了,所以这里省略。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值