小文件处理(自定义InputFormat)

1.需求分析

无论hdfs还是mapreduce,对于小文件都有损效率,实践中,又难免面临处理大量小文件的场景,此时,就需要有相应解决方案。将多个小文件合并成一个文件SequenceFile,SequenceFile里面存储着多个文件,存储的形式为文件路径+名称为key,文件内容为value。

2.数据准备

one.txt

yongpeng weidong weinan
sanfeng luozong xiaoming

two.txt

longlong fanfan
mazong kailun yuhang yixin
longlong fanfan
mazong kailun yuhang yixin

three.txt

shuaige changmo zhenqiang
dongli lingu xuanxuan

最终预期文件格式:

3.优化分析

小文件的优化无非以下几种方式:

(1)在数据采集的时候,就将小文件或小批数据合成大文件再上传HDFS

(2)在业务处理之前,在HDFS上使用mapreduce程序对小文件进行合并

(3)在mapreduce处理时,可采用CombineTextInputFormat提高效率

4.具体实现

本节采用自定义InputFormat的方式,处理输入小文件的问题。

(1)自定义一个类继承FileInputFormat

(2)改写RecordReader,实现一次读取一个完整文件封装为KV

(3)在输出时使用SequenceFileOutPutFormat输出合并文件

5.代码实现

(1)自定义InputFromat

package com.xyg.mapreduce.inputformat;

import java.io.IOException;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.BytesWritable;
import org.apache.hadoop.io.NullWritable;
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; public class WholeFileInputformat extends FileInputFormat<NullWritable, BytesWritable>{ @Override
protected boolean isSplitable(JobContext context, Path filename) {
return false;
} @Override
public RecordReader<NullWritable, BytesWritable> createRecordReader(InputSplit split, TaskAttemptContext context)
throws IOException, InterruptedException {
// 1 定义一个自己的recordReader
WholeRecordReader recordReader = new WholeRecordReader(); // 2 初始化recordReader
recordReader.initialize(split, context); return recordReader;
}
}

(2)自定义RecordReader

package com.xyg.mapreduce.inputformat;

import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.BytesWritable;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.mapreduce.InputSplit;
import org.apache.hadoop.mapreduce.RecordReader;
import org.apache.hadoop.mapreduce.TaskAttemptContext;
import org.apache.hadoop.mapreduce.lib.input.FileSplit; public class WholeRecordReader extends RecordReader<NullWritable, BytesWritable> {
private FileSplit split;
private Configuration configuration; private BytesWritable value = new BytesWritable();
private boolean processed = false; @Override
public void initialize(InputSplit split, TaskAttemptContext context) throws IOException, InterruptedException {
// 获取传递过来的数据
this.split = (FileSplit) split;
configuration = context.getConfiguration();
} @Override
public boolean nextKeyValue() throws IOException, InterruptedException { if (!processed) {
// 1 定义缓存
byte[] contents = new byte[(int) split.getLength()]; // 2 获取文件系统
Path path = split.getPath();
FileSystem fs = path.getFileSystem(configuration); // 3 读取内容
FSDataInputStream fis = null;
try {
// 3.1 打开输入流
fis = fs.open(path); // 3.2 读取文件内容
IOUtils.readFully(fis, contents, , contents.length); // 3.3 输出文件内容
value.set(contents, , contents.length);
} catch (Exception e) { } finally {
IOUtils.closeStream(fis);
} processed = true; return true;
} return false;
} @Override
public NullWritable getCurrentKey() throws IOException, InterruptedException { return NullWritable.get();
} @Override
public BytesWritable getCurrentValue() throws IOException, InterruptedException { return value;
} @Override
public float getProgress() throws IOException, InterruptedException {
return processed?:;
} @Override
public void close() throws IOException { }
}

(3)InputFormatDriver处理流程

package com.xyg.mapreduce.inputformat;

import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.BytesWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.InputSplit;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.input.FileSplit;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.mapreduce.lib.output.SequenceFileOutputFormat;
public class InputFormatDriver { static class SequenceFileMapper extends Mapper<NullWritable, BytesWritable, Text, BytesWritable> {
private Text k = new Text();; @Override
protected void map(NullWritable key, BytesWritable value, Context context)
throws IOException, InterruptedException { // 获取切片信息
InputSplit split = context.getInputSplit();
// 获取切片路径
Path path = ((FileSplit) split).getPath();
// 根据切片路径获取文件名称
k.set(path.toString()); // 文件名称为key
context.write(k, value);
}
} public static void main(String[] args) throws Exception {
args = new String[] { "e:/inputinputformat", "e:/output1" }; Configuration conf = new Configuration(); Job job = Job.getInstance(conf);
job.setJarByClass(InputFormatDriver.class);
job.setMapperClass(SequenceFileMapper.class);
job.setNumReduceTasks();
job.setInputFormatClass(WholeFileInputFormat.class);
job.setOutputFormatClass(SequenceFileOutputFormat.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(BytesWritable.class);
FileInputFormat.setInputPaths(job, new Path(args[]));
FileOutputFormat.setOutputPath(job, new Path(args[])); boolean result = job.waitForCompletion(true); System.exit(result ? : );
}
}

Hadoop案例(六)小文件处理(自定义InputFormat)的更多相关文章

  1. MR案例:小文件处理方案

    HDFS被设计来存储大文件,而有时候会有大量的小文件生成,造成NameNode资源的浪费,同时也影响MapReduce的处理效率.有哪些方案可以合并这些小文件,或者提高处理小文件的效率呢? 1). 所 ...

  2. 关于hadoop处理大量小文件情况的解决方法

    小文件是指那些size比HDFS的block size(默认64m)小的多的文件.任何一个文件,目录和bolck,在HDFS中都会被表示为一个object存储在namenode的内存中,每一个obje ...

  3. 【Hadoop离线基础总结】MapReduce自定义InputFormat和OutputFormat案例

    MapReduce自定义InputFormat和OutputFormat案例 自定义InputFormat 合并小文件 需求 无论hdfs还是mapreduce,存放小文件会占用元数据信息,白白浪费内 ...

  4. 基于Hadoop Sequencefile的小文件解决方案

    一.概述 小文件是指文件size小于HDFS上block大小的文件.这样的文件会给hadoop的扩展性和性能带来严重问题.首先,在HDFS中,任何block,文件或者目录在内存中均以对象的形式存储,每 ...

  5. Hadoop处理大量小文件的问题和解决方法

    小文件指的是那些size比HDFS的block size(默认64M)小的多的文件.如果在HDFS中存储小文件,那么在HDFS中肯定会含有许许多多这样的小文件(不然就不会用hadoop了).而HDFS ...

  6. MR案例:小文件合并SequeceFile

    SequeceFile是Hadoop API提供的一种二进制文件支持.这种二进制文件直接将<key, value>对序列化到文件中.可以使用这种文件对小文件合并,即将文件名作为key,文件 ...

  7. hadoop spark合并小文件

      一.输入文件类型设置为 CombineTextInputFormat hadoop job.setInputFormatClass(CombineTextInputFormat.class) sp ...

  8. 如何利用Hadoop存储小文件

    **************************************************************************************************** ...

  9. 用Hadoop AVRO进行大量小文件的处理(转)

    使用 使用使用 使用 HDFS 保存大量小文件的缺点:1.Hadoop NameNode 在内存中保存所有文件的“元信息”数据.据统计,每一个文件需要消耗 NameNode600 字节内存.如果需要保 ...

  10. Hive小文件处理

    小文件是如何产生的: 动态分区插入数据的时候,会产生大量的小文件,从而导致map数量的暴增 数据源本身就包含有大量的小文件 reduce个数越多,生成的小文件也越多 小文件的危害: 从HIVE角度来看 ...

随机推荐

  1. Linux基础--------监控系统、进程管理、软件包管理-------free、dd、kill、 rpm、yum、源码安装python

    作业一:1) 开启Linux系统前添加一块大小为15G的SCSI硬盘 2) 开启系统,右击桌面,打开终端 3) 为新加的硬盘分区,一个主分区大小为5G,剩余空间给扩展分区,在扩展分区上划分1个逻辑分区 ...

  2. STL源码分析-iterator

    http://note.youdao.com/noteshare?id=4efcb6441063dae956c226f91c161897

  3. Android Monkey 脚本编写与检查内存泄露

    一.Monkey脚本编写 1.Monkey脚本格式 脚本优势: 简单快捷,不需要接触任何工具,只需要一个记事本文件 脚本缺点: 实现坐标.按键等基本操作的相应步骤,顺序脚本无逻辑性 脚本源码: \de ...

  4. tp between

    $a = array( 'time' => array('between',[c,d]) ); c<= time <= d

  5. #define _INTSIZEOF(n) ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) )

    原文 功能: 首先,sizeof(int)肯定是2的次方数,比如32位是4,64位是8 ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) ) 的意思就 ...

  6. Jquery 操作 Select 详解

    jQuery是如何控制和操作select的.先看下面的代码 比如<select class="selector"></select> 1.设置value为p ...

  7. mac activemq

    安装 brew install maven 运行 To have launchd start activemq now and restart at login: brew services star ...

  8. 谷歌地图 API 开发之添加标记(解析以及补充)

    今天又看了下官网,发现官网上有地图标记的详细说明.当时居然眼瞎看不见,还琢磨了好久...#$%^&,一定是项目太急,没看到(^o^)/~地址:https://developers.google ...

  9. matlab的rem()和mod()函数

    matlab的rem()和mod()函数 rem(x,y):求整除x/y的余数 mod(x,y):求模 rem(x,y)=x-y.*fix(x./y);  (fix()向0取整) mod(x,y)=x ...

  10. .Net公用代码

    创建txt文本文件 #region 创建txt文本文件 /// <summary> /// 创建txt文本文件 /// </summary> /// <param nam ...