hadoop:MapperReducer之最大气温值

1.前期准备

1.1.hadoop集群环境

1个结点master运行namenode,jobtracker,3个结点运行datanode,tasktracker:

域名IP运行服务
master192.168.1.3nodenode,jobtracker
slaver1192.168.122.68datanode
slaver2192.168.122.153datanode
slaver3192.168.122.98datanode

 

1.2数据准备

气象数据从ncdn下载,这里的测试使用的是1990年的统计数据,具体下载地址:ftp://ftp.ncdc.noaa.gov/pub/data/gsod/1990/gsod_1990.tar

下载下来是一个tar包,tar中有一些.gz压缩文件,每个压缩文件包含一些气象统计数据,使用gunzip解压出来一个文件观察一下:

uzero@uzero:~/test-data/1990$ gunzip 999999-41406-1990.op.gz
uzero@uzero:~/test-data/1990$ less 999999-41406-1990.op
STN--- WBAN   YEARMODA    TEMP       DEWP      SLP        STP       VISIB      WDSP     MXSPD   GUST    MAX     MIN   PRCP   SNDP   FRSHTT
999999 41406  19900101    81.5 24    72.1 24  1011.6 24  1002.4 24    7.0 24    7.0 24   12.0  999.9    87.1*   77.0*  0.00I 999.9  000000
999999 41406  19900102    81.4 24    70.2 24  1012.1 24  1002.7 24    7.0 24    7.2 24   14.0  999.9    87.1*   77.0*  0.00I 999.9  000000

可以看到第4列就是气温值。每个从.gz解压出来的文件是1990年气象数据的一部分,为了统计1990年气温最高值需要对这些分散的文件进行下处理,将他们合并成一个大的文件;

#!/usr/bin/env bash

for file in ./*
do
    gunzip -c `basename $file` | sed '1d' >> 1990
done

先将gsod_1990.tar拷贝到一个目录下,然后解压该tar包,删除gsod_1990.tar,执行上面的脚本,就会将所有气象记录合并到1990这个文件中,脚本使用sed的删除每个记录文件的title。

2.找出最大气温

2.1.使用shell脚本

观察气象记录,会发现每行代表一天的观测记录,包括气象站,气温,空气质量等等字段,这些字段被空白符分割,很容易想到用awk将气温字段拿出来,再逐行做对比找出最大值:

 

#!/usr/bin/env bash                                                                                                                     

cat $1 | awk 'BEGIN{max=0} {temp=$4 + 0;{if(temp >= max) max = temp}} END{print "max temperature: " max}'

以1990做为参数执行这个脚本就会获得结果:

uzero@uzero:~/test-data/1990$ /home/uzero/code/bash/max_temperature.sh 1990
max temperature: 109.8

 

2.2.MapperReducer

现在用MapperReducer实现该功能,MapperReducer分为两个阶段,map阶段和reduce阶段,map阶段的输出是reduce阶段的输入,每个阶段都以key/value作为输入和输出。对于map阶段,输入的key是该行在文件中的偏移量,value就是该行的内容,偏移量直接忽略掉;输出的key是从每行提取的年份,value是从每行提取的气温值。对于reduce阶段,输入的key是年份,value是气温值;输出的key是年份,气温是该年最大的气温值。

2.2.1.代码实现

下面实现MaxTemperature类

import java.io.IOException;

import org.apache.hadoop.io.FloatWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;

public class MaxTemperatureMapper extends  Mapper<Object, Text, Text, FloatWritable> {

    public void map(Object key, Text values,
            Context context) throws IOException, InterruptedException{
        String[] allRecord = values.toString().split("\\s+");
        String year = allRecord[2].substring(0, 4);
        float airTemperature = Float.parseFloat(allRecord[3]);
        context.write(new Text(year), new FloatWritable(airTemperature));
    }
}

下面实现MaxTemeprature类

import java.io.IOException;

import org.apache.hadoop.io.FloatWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;


public class MaxTemperatureReducer extends Reducer<Text, FloatWritable, Text, FloatWritable>{
    public void reduce(Text key, Iterable<FloatWritable> values,
            Context context) throws IOException, InterruptedException{
        float maxTemperatur = Integer.MIN_VALUE;
        for(FloatWritable val : values) {
            maxTemperatur = Math.max(maxTemperatur, val.get());
        }
        context.write(key, new FloatWritable(maxTemperatur));
    }

}

下面实现负责运行mapreduce作业的MaxTemeprature类

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.FloatWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.GenericOptionsParser;


public class MaxTemperature {

    public static void main(String[] args) throws Exception {
        Configuration conf = new Configuration();
        String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();
        if(otherArgs.length != 2){
            System.out.println("Usage: MaxTemperature <input path> <output path>");
            System.exit(-1);
        }
        Job job = new Job(conf, "max temperature");
        
        // TODO: specify output types
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(FloatWritable.class);
        job.setJarByClass(MaxTemperature.class);
        job.setMapperClass(MaxTemperatureMapper.class);
        job.setReducerClass(MaxTemperatureReducer.class);
        FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
        FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));
        System.exit(job.waitForCompletion(true) ? 0 : 1);
    }
}
 2.2.2.eclipse运行mapreduce

首先在eclipse(需要配置eclipse插件)中展开DFS Location:

在hadoop子目录下面选择一个文件夹,右击该文件夹,选择UpLoad files to DFS,将1990文件copy的hdfs文件系统中

右击工程->Run As->Run Configurations弹出配置框,在左边栏新建一个Java Application配置,会在右边弹出配置栏,Main标签选择包含main方法的类名MaxTemeprature,Arguments标签填写参数,主要是填写输入文件路径和输入文件路径,输入文件路径必须要填写刚才upload到hdfs文件系统的路径,输入路径可以填写本地文件系统,这里选择将输出结果放到本地文件系统(本地文件系统以file:///开始)/home/uzero/1990-result文件夹下

hdfs://uzero:54310/user/uzero/1990 file:///home/uzero/1990-result

配置好后,点击Apply->Run

查看结果:

uzero@uzero:~/1990-output$ cd /home/uzero/1990-output/
uzero@uzero:~/1990-output$ cat part-r-00000 
1990    109.8

和使用shell脚本计算的结果是一样的。

2.2.3.使用hadoop命令运行mapreduce

如果没有eclipse的话,可以使用hadoop命令的jar选项来运行mapreduce:

首先先将1990文件拷贝到hdfs中,可以使用hadoop命令的-copyFromLocal选项,也可以使用-put选项:

uzero@uzero:~$ hadoop dfs -put ./1990 1990

或者:

hadoop dfs -copyFromLocal ./1990 1990

然后编译mapreduce代码:

uzero@uzero:~/code/mapreduce/MaxTemeperatur$ ls
MaxTemperature.java   MaxTemperatureMapper.java   MaxTemperatureReducer.java
uzero@uzero:~/code/mapreduce/MaxTemeperatur$ javac *.java
uzero@uzero:~/code/mapreduce/MaxTemeperatur$ ls
MaxTemperature.class  MaxTemperatureMapper.class  MaxTemperatureReducer.class
MaxTemperature.java   MaxTemperatureMapper.java   MaxTemperatureReducer.java

编译以前需要先将hadoop的hadoop-core-1.0.4.jar,commons-logging-1.1.1.jar,commons-logging-api-1.0.4.jar,commons-cli-1.2.jar这几个jar添加到CLASSPATH路径中,否则编译会报错。

打包执行mapreduce:

uzero@uzero:~/code/mapreduce/MaxTemeperatur$ jar cvf MaxTemperature.jar *.class
uzero@uzero:~/code/mapreduce/MaxTemeperatur$ ls
MaxTemperature.class  MaxTemperature.java         MaxTemperatureMapper.java    MaxTemperatureReducer.java
MaxTemperature.jar    MaxTemperatureMapper.class  MaxTemperatureReducer.class
uzero@uzero:~/code/mapreduce/MaxTemeperatur$ hadoop jar MaxTemeprature.jar MaxTemperature hdfs://uzero:54310/user/uzero/1990 file:///home/uzero/1990-output/

这里需要注意的是,该命令只能在运行jobtracker的机器上运行,如果你的namenode和jobtracker不在一个机器上,需要将该包拷贝到运行jobtracker的机器上运行该命令,否则会报MaxTemperatureMapper类找不到,这是因为运行mapreduce任务需要每个datanode上都要有该jar包(mapreduce任务运行在datanode上),而jobtracker会将jar包拷贝每个datanode上,不在jobtracker上运行就没法将jar包拷贝到datanode上。

 

 

 

 

 

 

 

 

转载于:https://www.cnblogs.com/uzero/archive/2013/05/03/3054924.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值