案例一:基于MapReduce求每年的最大天气
一、准备条件:
1、数据源:两个“.gz”文件,分别为1901.gz/192.gz
2、Hadoop集群环境
二、数据源分析:
1、第16-20位为年份信息
2、第88位为+号时89-93为温度信息,为-号时88-93为温度信息
3、提取后数据举例为:
(1901,0)
(1901,22)
(1901,-11)
。。。。。。
三、概念
1、并行计算: Map<Key,value>
entry:条目(key-value)
Key:行号,0为基址
K-V-->map-->K-V
2、shuffle:洗牌
四、运行机制
![](http://i.imgur.com/odHFV8J.png)
五、功能实现
前提准备:
- 引入类库将Hadoop包解压,并进入相对路径为hadoop-2.7.2\share\hadoop目录下,搜索*.jar,全选复制到新建的lib目录下,并在该目录下搜索source.jar(为源码包),删除;并在该目录下搜索test(测试包),删除,剩下的就是可用的包。
- 新建项目命名为Hadoop-mr-01 新建lib文件夹,将第一步所找到的jar包复制到该文件夹下,并引入到项目中
目录结构图:
第一步
新建MaxTemperatureMapper.java
类继承于org.apache.hadoop.mapreduce.Mapper<KEYIN, VALUEIN, KEYOUT, VALUEOUT>
并将四个参数修改为org.apache.hadoop.mapreduce.Mapper<LongWritable, Text, Text, IntWritable>
说明:Mapper类下四个参数说明,输入的Key的值,输入的Value值,输出的Key的值,输出的Value值,也就是入的行号,输入的一行的文本,年份,温度
代码如下:
package com.xt.hadoop;
import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
public class MaxTemperatureMapper extends Mapper<LongWritable, Text, Text, IntWritable> {
//缺失
private static final int MISSING=9999;
//提取信息
@Override
protected void map(LongWritable key, Text value,Context context)
throws IOException, InterruptedException {
//获取一行的数据
String line = value.toString();
//在一行数据中提取年份数据 也就是第16-20位
String year = line.substring(15,19);
//气温变量
int airTemperature;
if (line.charAt(87)=='+') {
airTemperature=Integer.parseInt(line.substring(88,92));
}
else {
airTemperature=Integer.parseInt(line.substring(87,92));
}
//质量
String quality=line.substring(92,93);
//将有效数据写入到map的context中,注意类型务必要和泛型声明一致
if (airTemperature!=MISSING&&quality.matches("[01459]")) {
context.write(new Text(year),new IntWritable(airTemperature));
}
}
}
第二步
新建MaxTemperatureReducer.java
类继承于org.apache.hadoop.mapreduce.Reducer<KEYIN, VALUEIN, KEYOUT, VALUEOUT>
并将四个参数修改为org.apache.hadoop.mapreduce.Reducer<Text, IntWritable, Text, IntWritable>
说明:mapper工作完成之后要交给reduce,因为mapper的输出为Text, IntWritable所以Reducer的输入要为mapper的输出,即Text, IntWritable,输出为Text, IntWritable
代码如下:
package com.xt.hadoop;
import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
public class MaxTemperatureReducer extends Reducer<Text, IntWritable, Text, IntWritable> {
@Override
protected void reduce(Text keyin, Iterable<IntWritable> values, Context context)
throws IOException, InterruptedException {
//定义最大值变量
int maxValue=Integer.MIN_VALUE;
for (IntWritable intWritable : values) {
maxValue=Math.max(maxValue, intWritable.get());
}
//将Reduce写入context
context.write(keyin, new IntWritable(maxValue));
}
}
第三步
新建MaxTemperature.java
类,实现main方法
具体代码如下:
package com.xt.hadoop;
import java.io.IOException;
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.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
public class MaxTemperature {
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
//作业
Job job = new Job();
job.setJarByClass(MaxTemperature.class);
//设置作业名称 便于调试
job.setJobName("Max Temperature");
//添加输入路径,可以添加多个路径
//输入不进可以是具体文件,还可以是目录,不会递归
FileInputFormat.addInputPath(job, new Path(args[0]));
//设置输出路径,只能添加一个,而且不能存在
FileOutputFormat.setOutputPath(job, new Path(args[1]));
//设置mapper
job.setMapperClass(MaxTemperatureMapper.class);
//设置reducer
job.setReducerClass(MaxTemperatureReducer.class);
//设置输出key类
job.setOutputKeyClass(Text.class);
//设置输出Value类
job.setOutputValueClass(IntWritable.class);
//等待作业完成
System.out.println(job.waitForCompletion(true));
}
}
六、项目部署
前提准备
1、将项目生成JAR文件,并将Jar文件放到master主机中
注:生成过程中JAR包全部不选择
在第三步需要设置主函数类
2、将天气数据上传到hdfs文件系统中
第一步:通过WinSCP将生成的Jar文件拷贝到/usr/local目录下
第二步:通过WinSCP将天气数据文件靠背到/usr/local目录下
并执行命令:
1、在HDFS创建 `hadoop fs -mkdir -p /ncdc`
2、将天气数据文件上传到HDFS /ncdc目录下 hadoop fs -put 19*.gz /ncdc
3、执行Jar文件 hadoop jar hadoopmr01.jar /ncdc /out
运行结果如下图所示
out目录如下图所示
part-r-00000为数据文件
查看数据文件内如如下hadoop fs -cat /out/part*