MapReduce 框架原理



1.InputFormat可以对Mapper的输入进行控制

2.Reducer阶段会主动拉取Mapper阶段处理完的数据

3.Shuffle可以对数据进行排序、分区、压缩、合并,核心部分。

4.OutPutFomat可以对Reducer的输出进行控制

4.OutputFormat数据输出

OutputFormat接口实现类

OutputFormat是MapReduce输出的基类,所有MapReduce输出都实现了OutputFormat接口

  • OutputFormat

    • FileOutputFormat

      • TextOutputFormat 默认

自定义OutputFormat

应用场景

输出数据到MySQL/HBase等

自定义OutputFormat步骤

1.自定义一个类继承FileOutputFormat<k,v> 这里的kv是指输入的kv

2.重写getRecordWriter方法

3.创建返回类RecordWeiter,kv同1,改写输出数据的方法write()

自定义OutputFormat案例

需求

过滤输入的log日志,包含ranan的网站输出到D:\hadoop_data\output\ranan.log,不包含ranan的网站输出到D:\hadoop_data\output\other.log

输入数据:D:\hadoop_data\input\inputoutputformat\log.txt

http://www.baidu.com
http://www.google.com
http://cn.bing.com
http://www.ranan.com
http://www.sohu.com
http://www.sina.com
http://www.sin2a.com
http://www.sin2desa.com
http://www.sindsafa.com

需求分析

分区输出的文件名不能自己命名,所以这里采用自定义OutputFormat类

1.创建一个类LogRecordWriter继承RecordWriter

1.1 创建两个文件的输出流:rananOut、otherOut

1.2 如果包含ranan,输出到rananOut流,如果不包含ranan,输出到otherOut流

2.在job驱动中配置使用自定义类job.setOutFormatClass(LogRecordWriter.class)

案例实现

LogMapper类

输入的k是偏移量LongWritable,输入的v是一行Text。观察输出只需要一行网站,那么输出的k是一行类容,输出的v是NullWritable

为什么不k是空,因为k是会排序的,需要实现可排序

package ranan.mapreduce.outputformat;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import java.io.IOException;
public class LogMapper extends Mapper <LongWritable,Text,Text, NullWritable>{
@Override
protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, NullWritable>.Context context) throws IOException, InterruptedException {
context.write(value,NullWritable.get());
}
}

LogReducer

只起到数据传递的作用

注意要防止两条一样的进来输出一条出去的情况

package ranan.mapreduce.outputformat;

import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer; import java.io.IOException; public class LogReducer extends Reducer<Text, NullWritable,Text,NullWritable> {
@Override
protected void reduce(Text key, Iterable<NullWritable> values, Reducer<Text, NullWritable, Text, NullWritable>.Context context) throws IOException, InterruptedException { for(NullWritable value:values){
context.write(key,NullWritable.get());
}
//直接写进来两条一样的只会输出一条出去
//context.write(key,NullWritable.get());
}

LogOutputFormat类

package ranan.mapreduce.outputformat;

import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.RecordWriter;
import org.apache.hadoop.mapreduce.TaskAttemptContext;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; import java.io.IOException; public class LogOutputFormat extends FileOutputFormat<Text, NullWritable> {
@Override
public RecordWriter<Text, NullWritable> getRecordWriter(TaskAttemptContext job) throws IOException, InterruptedException {
//这里返回值需要RecordWriter类,创建这个类 传递job配置信息!
LogRecordWriter lrw = new LogRecordWriter(job);
return lrw;
}
}

LogRecordWriter类

作为RecordWriter方法的返回值,主要的实现写在这里

package ranan.mapreduce.outputformat;

import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.RecordWriter;
import org.apache.hadoop.mapreduce.TaskAttemptContext; import java.io.IOException; public class LogRecordWriter extends RecordWriter<Text, NullWritable> { private FSDataOutputStream rananOut;
private FSDataOutputStream otherOut; //与自定义LogOutputFormat产生联系
public LogRecordWriter(TaskAttemptContext job) {
//创建两条输出流
try {
//get的报错直接处理,参数的配置信息使用job的配置信息
FileSystem fs = FileSystem.get(job.getConfiguration());
rananOut = fs.create(new Path("D:\\hadoop_data\\output\\ranan.log"));
otherOut = fs.create(new Path("D:\\hadoop_data\\output\\other.log"));
} catch (IOException e) {
e.printStackTrace();
} } @Override
public void write(Text key, NullWritable value) throws IOException, InterruptedException {
//具体写
//输入是每一行的内容,类型是Text
String log = key.toString();
if(log.contains("ranan")) {
rananOut.writeBytes(log);
}
else {
//writeBytes参数是string类型
otherOut.writeBytes(log);
} }
//资源关闭
@Override
public void close(TaskAttemptContext context) throws IOException, InterruptedException {
IOUtils.closeStream(rananOut);
IOUtils.closeStream(otherOut); //TOUtiles工具类
}
}

LogDriver类

虽然我们自定义OutputFormat继承了FileOutputFormat,自定义了输出路径。

而FileOutputFormat需要输出一个_SUCCESS文件,依旧需要设置一个输出路径输出_SUCCESS文件

package ranan.mapreduce.outputformat;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.NullWritable;
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 java.io.IOException; public class LogDriver {
public static void main(String[] args) throws IOException, InterruptedException, ClassNotFoundException {
// 1 获取job
Configuration conf = new Configuration();
Job job = Job.getInstance(conf); //2 设置jar
job.setJarByClass(LogDriver.class); //3 关联Mapper,Reducer
job.setMapperClass(LogMapper.class);
job.setReducerClass(LogReducer.class); // 4 设置mapper 输出的key和value类型
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(NullWritable.class); // 5 设置最终数据输出的key和value类型
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(NullWritable.class); // 设置自定义的outputFormat
job.setOutputFormatClass(LogOutputFormat.class); // 6 设置数据的输入路径和输出路径
FileInputFormat.setInputPaths(job, new Path("D:\\hadoop_data\\input\\inputoutputformat\\log.txt"));
//虽然我们自定义OutputFormat继承了FileOutputFormat,而FileOutputFormat需要输出一个_SUCCESS文件,依旧需要设置一个输出路径输出_SUCCESS文件
FileOutputFormat.setOutputPath(job, new Path("D:\\hadoop_data\\output\\sucess")); // 7 提交job
boolean result = job.waitForCompletion(true);
System.exit(result ? 0 : 1);
}
}

输出结果

发现other.log里的网址连在一起了,输出的时候没输出回车

修改LogRecordWriter类

if(log.contains("ranan")) {
rananOut.writeBytes(log + "\n");
}
else {
//writeBytes参数是string类型
otherOut.writeBytes(log+ "\n");
}

MapReduce05 框架原理OutPutFormat数据输出的更多相关文章

  1. 新增访客数量MR统计之MR数据输出到MySQL

    关注公众号:分享电脑学习回复"百度云盘" 可以免费获取所有学习文档的代码(不定期更新)云盘目录说明:tools目录是安装包res 目录是每一个课件对应的代码和资源等doc 目录是一 ...

  2. 把数据输出到Word (组件形式)

    上一篇的文章中我们介绍了在不使用第三方组件的方式,多种数据输出出到 word的方式,最后我们也提到了不使用组件的弊端,就是复杂的word我们要提前设置模板.编码不易控制.循环输出数据更是难以控制.接下 ...

  3. 把数据输出到Word (非插件形式)

    项目开发过程中,我们要把数据以各种各样的形式展现给客户.把数据以文档的形式展现给客户相信是一种比较头疼的问题,如果没有好的方法会 使得我的开发繁琐,而且满足不了客户的需求.接下来我会通过两种开发方式介 ...

  4. jquery: json树组数据输出到表格Dom树的处理方法

    项目背景 项目中需要把表格重排显示 处理方法 思路主要是用历遍Json数组把json数据一个个append到5个表格里,还要给每个单元格绑定个单击弹出自定义对话框,表格分了单双行,第一行最后还要改ro ...

  5. 【matlab】将matlab中数据输出保存为txt或dat格式

    将matlab中数据输出保存为txt或dat格式 总结网上各大论坛,主要有三种方法. 第一种方法:save(最简单基本的) 具体的命令是:用save *.txt -ascii x x为变量 *.txt ...

  6. 将matlab中数据输出保存为txt或dat格式

    :FID= FOPEN(filename,permission) 用指定的方式打开文件 FID=+N(N是正整数):表示文件打开成功,文件代号是N. FID=-1            : 表示文件打 ...

  7. ffmpeg 从内存中读取数据(或将数据输出到内存)

    更新记录(2014.7.24): 1.为了使本文更通俗易懂,更新了部分内容,将例子改为从内存中打开. 2.增加了将数据输出到内存的方法. 从内存中读取数据 ffmpeg一般情况下支持打开一个本地文件, ...

  8. 使用MapReduce查询Hbase表指定列簇的全部数据输出到HDFS(一)

    package com.bank.service; import java.io.IOException; import org.apache.hadoop.conf.Configuration;im ...

  9. 《物联网框架ServerSuperIO教程》- 22.动态数据接口增加缓存,提高数据输出到OPCServer和(实时)数据库的效率

     22.1   概述及要解决的问题 设备驱动有DeviceDynamic接口,可以继承并增加新的实时数据属性,每次通讯完成后更新这些属性数据.原来是通过DeviceDynamic接口实体类反射的方式获 ...

随机推荐

  1. Apache Kafka 学习笔记

    1. 介绍Kafka是由Apache软件基金会开发的一个开源流处理平台,由Scala和Java编写.Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者在网站中的所有动作流数据. 这种动 ...

  2. 从零开始的DIY智能家居 - 基于 ESP32 的智能水浊度传感器

    前言 家里有个鱼缸养了几条鱼来玩玩,但是换水的问题着实头疼,经常一个不注意就忘记换水,鱼儿就没了.o(╥﹏╥)o 在获得 Spirit 1 边缘计算机 后就相当于有了一个人智能设备服务器,可以自己开发 ...

  3. Luogu P1563 [NOIp2016提高组]玩具谜题 | 模拟

    题目链接 纯模拟题,没啥好说的,就是要判断地方有点多,一定要注意细节. #include<iostream> #include<cstdio> #include<fstr ...

  4. Centos 8 阿里yum源配置

    编辑 CentOS-AppStream.repo配置文件,注释原有url,加入以下url baseurl=https://mirrors.aliyun.com/centos/$releasever/A ...

  5. Spring Cloud Gateway实战之一:初探

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 关于<Spring Cloud Gateway实 ...

  6. laravel常用查询

    插入 DB::table('t_admin_users')->insert([ [ 'role_id' => $allData['roleId'], 'username' => $a ...

  7. C++ 函数模板和函数重载同时出现如何调用

    C++ 函数模板和函数重载同时出现如何调用 重点 函数模板不允许自动转换,普通函数可以进行自动类型转换 函数模板可以像普通函数一样被重载 C++编译器优先考虑调用普通函数 如果函数模板可以产生一个更好 ...

  8. 了解一下Git的常用语句

    简单学习了一下Git,整理了一点常用语句 http连接 git clone https://仓库地址 连接githup cd shop 进入文件夹 git config --global user.n ...

  9. LeetCode刷题 字符串详解

    一.字符串常用的操作 1. string类 1.1 string的定义与初始化 1.1.1 string的定义 1.1.2 string的初始化 1.2 string的赋值与swap.大小操作.关系运 ...

  10. 那一天,我被Redis主从架构支配的恐惧

    面试官:要不你来讲讲你最近在看的点呗?可以拉出来一起讨论下(今天我也不知道要问什么) 候选者:最近在看「Redis」相关的内容 面试官:嗯,我记得已经问过Redis的基础和持久化了 面试官:要不你来讲 ...