您的位置:首页 > 运维架构

Hadoop系列修炼---入门笔记16

2018-02-05 10:52 260 查看
核心内容:

1、数据倾斜

2、链式处理map和reduce tasks

1、数据倾斜

    1.reduce

    2.自定义分区函数

        数据结果错 + 二次job

    3.重新设计key

        数据结果错 + 二次job

2、链式处理map和reduce tasks

一:背景

Hadoop2.0开始MapReduce作业支持链式处理,类似于富士康生产苹果手机的流水线,每一个阶段都有特定的任务要处理,比如提供原配件——>组装——打印出厂日期,等等。通过这样进一步的分工,从而提高了生成效率,我们Hadoop中的链式MapReduce也是如此,这些Mapper可以像水流一样,一级一级向后处理,有点类似于Linux的管道。前一个Mapper的输出结果直接可以作为下一个Mapper的输入,形成一个流水线。

注:链式MapReduce的执行规则:整个Job中只能有一个Reducer,在Reducer前面可以有一个或者多个Mapper,在Reducer的后面可以有0个或者多个Mapper。

二:技术实现

#需求:现有如下销售数据,要求使用链式MapReduce,在第一个Mapper中过滤金额大于10000的数据,在第二个Mapper中过滤数据在100-10000之间的数据,在Reduce中进行分类汇总,在Reduce后面的Mapper中过滤掉商品名长度大于8的数据。

Phone	5000
Computer	2000
Clothes	300
XieZi	1200
QunZi	434
ShouTao	12
Books	12510
SmallShangPing	5
SmallShangPing	3
DingCan	2
代码实现:

public class ChainMapReduce {

// 定义输入输出路径
private static final String INPUTPATH = "hdfs://liaozhongmin21:8020/chainFiles/*";
private static final String OUTPUTPATH = "hdfs://liaozhongmin21:8020/out";

public static void main(String[] args) {

try {

Configuration conf = new Configuration();
// 创建文件系统
FileSystem fileSystem = FileSystem.get(new URI(OUTPUTPATH), conf);

// 判断输出路径是否存在,如果存在则删除
if (fileSystem.exists(new Path(OUTPUTPATH))) {
fileSystem.delete(new Path(OUTPUTPATH), true);
}

// 创建Job
Job job = new Job(conf, ChainMapReduce.class.getSimpleName());

// 设置输入目录
FileInputFormat.addInputPath(job, new Path(INPUTPATH));
// 设置输入文件格式
job.setInputFormatClass(TextInputFormat.class);

// 设置自定义的Mapper类
ChainMapper.addMapper(job, FilterMapper1.class, LongWritable.class, Text.class, Text.class, DoubleWritable.class, conf);
ChainMapper.addMapper(job, FilterMapper2.class, Text.class, DoubleWritable.class, Text.class, DoubleWritable.class, conf);
ChainReducer.setReducer(job, SumReducer.class, Text.class, DoubleWritable.class, Text.class, DoubleWritable.class, conf);
// 注:Reducer后面的Mapper也要用ChainReducer进行加载
ChainReducer.addMapper(job, FilterMapper3.class, Text.class, DoubleWritable.class, Text.class, DoubleWritable.class, conf);

// 设置自定义Mapper类的输出key和value
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(DoubleWritable.class);

// 设置分区
job.setPartitionerClass(HashPartitioner.class);
// 设置reducer数量
job.setNumReduceTasks(1);

// 设置自定义的Reducer类
// 设置输出的Key和value类型
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(DoubleWritable.class);

// 设置输出路径
FileOutputFormat.setOutputPath(job, new Path(OUTPUTPATH));
// 设置输出格式
job.setOutputFormatClass(TextOutputFormat.class);

// 提交任务
System.exit(job.waitForCompletion(true) ? 0 : 1);

} catch (Exception e) {
e.printStackTrace();
}
}

/**
* 过滤掉金额大于10000的记录
* @author 廖钟民 2015年3月17日下午6:27:05
*/
public static class FilterMapper1 extends Mapper<LongWritable, Text, Text, DoubleWritable> {

// 定义输出的key和value
private Text outKey = new Text();
private DoubleWritable outValue = new DoubleWritable();

@Override
protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, Double
95eb
Writable>.Context context) throws IOException,
InterruptedException {

// 获取行文本内容
String line = value.toString();

if (line.length() > 0) {
// 对行文本内容进行切分
String[] splits = line.split("\t");
// 获取money
double money = Double.parseDouble(splits[1].trim());
// 过滤
if (money <= 10000) {
// 设置合法结果
outKey.set(splits[0]);
outValue.set(money);
// 把合法结果写出去
context.write(outKey, outValue);
}
}
}
}

/**
* 过滤掉金额大于100的记录
* @author 廖钟民 2015年3月17日下午6:29:27
*/
public static class FilterMapper2 extends Mapper<Text, DoubleWritable, Text, DoubleWritable> {

@Override
protected void map(Text key, DoubleWritable value, Mapper<Text, DoubleWritable, Text, DoubleWritable>.Context context) throws IOException,
InterruptedException {
if (value.get() < 100) {

// 把结果写出去
context.write(key, value);
}
}
}

/**
* 金额汇总
* @author 廖钟民
*2015年3月21日下午1:46:47
*/
public  static class SumReducer extends Reducer<Text, DoubleWritable, Text, DoubleWritable> {
// 定义输出的value
private DoubleWritable outValue = new DoubleWritable();

@Override
protected void reduce(Text key, Iterable<DoubleWritable> values, Reducer<Text, DoubleWritable, Text, DoubleWritable>.Context context)
throws IOException, InterruptedException {

// 定义汇总结果
double sum = 0;
// 遍历结果集进行统计
for (DoubleWritable val : values) {

sum += val.get();
}
// 设置输出value
outValue.set(sum);
// 把结果写出去
context.write(key, outValue);
}
}

/**
* 过滤商品名称长度小于8的商品
* @author 廖钟民
*2015年3月21日下午1:47:01
*/
public  static class FilterMapper3 extends Mapper<Text, DoubleWritable, Text, DoubleWritable> {

@Override
protected void map(Text key, DoubleWritable value, Mapper<Text, DoubleWritable, Text, DoubleWritable>.Context context) throws IOException,
InterruptedException {
// 过滤
if (key.toString().length() < 8) {
// 把结果写出去
System.out.println("写出去的内容为:" + key.toString() +"++++"+ value.toString());
context.write(key, value);
}
}

}

}
注:驱动类中Reducer后面的Mapper必须应该通过ChainReducer来添加!

输出结果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: