MapReduce读取与输出

InputFormat

运⾏MapReduce程序时,输⼊的⽂件格式包括:基于⾏的⽇志⽂件、⼆进制格式⽂件、数据库表等。那
么,针对不同的数据类型,MapReduce是如何读取这些数据的呢?
InputFormat是MapReduce框架⽤来读取数据的类。

InputFormat常⻅⼦类包括:
TextInputFormat (普通⽂本⽂件,MR框架默认的读取实现类型)
KeyValueTextInputFormat(读取⼀⾏⽂本数据按照指定分隔符,把数据封装为kv类型)
NLineInputF ormat(读取数据按照⾏数进⾏划分分⽚)
CombineTextInputFormat(合并⼩⽂件,避免启动过多MapTask任务)
⾃定义InputFormat


CombineTextInputFormat案例

MR框架默认的TextInputFormat切⽚机制按⽂件划分切⽚,⽂件⽆论多⼩,都是单独⼀个切⽚,然后由⼀个MapTask处理,如果有⼤量⼩⽂件,就对应的会⽣成并启动⼤量的 MapTask,⽽每个MapTask处理的数据量很⼩⼤量时间浪费在初始化资源启动收回等阶段,这种⽅式导致资源利⽤率不⾼。
CombineTextInputFormat⽤于⼩⽂件过多的场景,它可以将多个⼩⽂件从逻辑上划分成⼀个切⽚,这样多个⼩⽂件就可以交给⼀个MapTask处理,提⾼资源利⽤率。需求将输⼊数据中的多个⼩⽂件合并为⼀个切⽚处理


运⾏WordCount案例,准备多个⼩⽂件,diver中添加如下代码

// 如果不设置InputFormat,它默认⽤的是TextInputFormat.class
 job.setInputFormatClass(CombineTextInputFormat.class);
 
 //虚拟存储切⽚最⼤值设置4m
 CombineTextInputFormat.setMaxInputSplitSize(job, 4194304);

CombineTextInputFormat切⽚原理

切⽚⽣成过程分为两部分:虚拟存储过程和切⽚过程
假设设置setMaxInputSplitSize值为4M
四个⼩⽂件:1.txt -->2M ;2.txt–>7M;3.txt–>0.3M;4.txt—>8.2M
**虚拟存储过程:**把输⼊⽬录下所有⽂件⼤⼩,依次和设置的setMaxInputSplitSize值进⾏⽐较,如果不⼤于设置的最⼤值,逻辑上划分⼀个块。如果输⼊⽂件⼤于设置的最⼤值且⼤于两倍,那么以最⼤值切割⼀块;当剩余数据⼤⼩超过设置的最⼤值且不⼤于最⼤值2倍,此时将⽂件均分成2个虚拟存储块(防⽌出现⼩切⽚)。 ⽐如如setMaxInputSplitSize值为4M,输⼊⽂件⼤⼩为8.02M,则先逻辑上分出⼀个4M的块。剩余的⼤⼩为4.02M,如果按照4M逻辑划分,就会出现0.02M的⾮常⼩的虚拟存储⽂件,所以将剩余的4.02M⽂件切分成(2.01M和2.01M)两个⽂件。

例如:
1.txt–>2M;2M<4M;⼀个块;
2.txt–>7M;7M>4M,但是不⼤于两倍,均匀分成两块;两块:每块3.5M;
3.txt–>0.3M;0.3<4M ,0.3M<4M ,⼀个块
4.txt–>8.2M;⼤于最⼤值且⼤于两倍;⼀个4M的块,剩余4.2M分成两块,每块2.1M

结果所有块信息:
2M,3.5M,3.5M,0.3M,4M,2.1M,2.1M 共7个虚拟存储块。

切⽚过程
1.判断虚拟存储的⽂件⼤⼩是否⼤于setMaxInputSplitSize值,⼤于等于则单独形成⼀个切⽚。
2.如果不⼤于则跟下⼀个虚拟存储⽂件进⾏合并,共同形成⼀个切⽚。
3.按照之前输⼊⽂件:有4个⼩⽂件⼤⼩分别为2M、7M、0.3M以及8.2M这四个⼩⽂件,则虚拟存储之后形成7个⽂件块,⼤⼩分别为: 2M,3.5M,3.5M,0.3M,4M,2.1M,2.1M

最终会形成3个切⽚,⼤⼩分别为: (2+3.5)M,(3.5+0.3+4)M,(2.1+2.1)M

注意:虚拟存储切⽚最⼤值设置最好根据实际的⼩⽂件⼤⼩情况来设置具体的值。


⾃定义InputFormat

HDFS还是MapReduce,在处理⼩⽂件时效率都⾮常低,但⼜难免⾯临处理⼤量⼩⽂件的场景,此时,就需要有相应解决⽅案。可以⾃定义InputFormat实现⼩⽂件的合并。

需求
将多个⼩⽂件合并成⼀个SequenceFile⽂件(SequenceFile⽂件是Hadoop⽤来存储⼆进制形式的key-value对的⽂件格式),SequenceFile⾥⾯存储着多个⽂件,存储的形式为⽂件路径+名称为key,⽂件内容为value。
结果
得到⼀个合并了多个⼩⽂件的SequenceFile⽂件
在这里插入图片描述

参考代码

CustomInputFormat和CustomRecordReader为自定义InputFormat的主要内容

CustomInputFormat

package com.lagou.mr.sequence;

//自定义inputFormat读取多个小文件,合并为一个SequenceFile文件
//SequenceFile文件中以kv形式存储文件,K-》文件路径+文件名称 value-》完整的文件的二进制内容

import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.BytesWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.InputSplit;
import org.apache.hadoop.mapreduce.JobContext;
import org.apache.hadoop.mapreduce.RecordReader;
import org.apache.hadoop.mapreduce.TaskAttemptContext;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;

import java.io.IOException;

//TextInputFormat中泛型是LongWritable,Text;指明当前inputFormat输出数据类型
public class CustomInputFormat extends FileInputFormat<Text, BytesWritable /*按字节读取文件,即实现完整的文件的二进制内容*/> {
   


    //重写是否可切分的方法
    @Override
    protected boolean isSplitable(JobContext context, Path filename
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值