Hadoop案例(六)小文件处理(自定义InputFormat)
小文件处理(自定义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)的更多相关文章
- MR案例:小文件处理方案
HDFS被设计来存储大文件,而有时候会有大量的小文件生成,造成NameNode资源的浪费,同时也影响MapReduce的处理效率.有哪些方案可以合并这些小文件,或者提高处理小文件的效率呢? 1). 所 ...
- 关于hadoop处理大量小文件情况的解决方法
小文件是指那些size比HDFS的block size(默认64m)小的多的文件.任何一个文件,目录和bolck,在HDFS中都会被表示为一个object存储在namenode的内存中,每一个obje ...
- 【Hadoop离线基础总结】MapReduce自定义InputFormat和OutputFormat案例
MapReduce自定义InputFormat和OutputFormat案例 自定义InputFormat 合并小文件 需求 无论hdfs还是mapreduce,存放小文件会占用元数据信息,白白浪费内 ...
- 基于Hadoop Sequencefile的小文件解决方案
一.概述 小文件是指文件size小于HDFS上block大小的文件.这样的文件会给hadoop的扩展性和性能带来严重问题.首先,在HDFS中,任何block,文件或者目录在内存中均以对象的形式存储,每 ...
- Hadoop处理大量小文件的问题和解决方法
小文件指的是那些size比HDFS的block size(默认64M)小的多的文件.如果在HDFS中存储小文件,那么在HDFS中肯定会含有许许多多这样的小文件(不然就不会用hadoop了).而HDFS ...
- MR案例:小文件合并SequeceFile
SequeceFile是Hadoop API提供的一种二进制文件支持.这种二进制文件直接将<key, value>对序列化到文件中.可以使用这种文件对小文件合并,即将文件名作为key,文件 ...
- hadoop spark合并小文件
一.输入文件类型设置为 CombineTextInputFormat hadoop job.setInputFormatClass(CombineTextInputFormat.class) sp ...
- 如何利用Hadoop存储小文件
**************************************************************************************************** ...
- 用Hadoop AVRO进行大量小文件的处理(转)
使用 使用使用 使用 HDFS 保存大量小文件的缺点:1.Hadoop NameNode 在内存中保存所有文件的“元信息”数据.据统计,每一个文件需要消耗 NameNode600 字节内存.如果需要保 ...
- Hive小文件处理
小文件是如何产生的: 动态分区插入数据的时候,会产生大量的小文件,从而导致map数量的暴增 数据源本身就包含有大量的小文件 reduce个数越多,生成的小文件也越多 小文件的危害: 从HIVE角度来看 ...
随机推荐
- form, table表示表格的时候有什么区别?
http://zhidao.baidu.com/link?url=1DFrMJlzV_fHSyGmKEi77ki6g2IrjrMfRGwVYNHL5Y8iJC9Diu2BoMGEiB3wbnkTCHm ...
- CSS盒子知识
此随笔写于学习完CSS盒子之后,所遇到的问题和感悟记录. 1.IE盒子: IE盒子的特性:对于IE浏览器来说width不是内容宽度.而是内容+外边距+边框的内容总和. 也就是说当盒子增加10px;那么 ...
- 单调队列 + 组合数统计 Gym 101102D
题目链接:http://codeforces.com/gym/101102/problem/D 题目大意:给你一个n*m的矩阵,矩阵里面的数值范围为[1,1e9].这个矩阵有一个值,如果相邻的多个数字 ...
- 【CodeForces】790 C. Bear and Company 动态规划
[题目]C. Bear and Company [题意]给定大写字母字符串,交换相邻字符代价为1,求最小代价使得字符串不含"VK"子串.n<=75. [算法]动态规划 [题解 ...
- laravel中form表单,ajax传值没反应
laravel中form表单,ajax传值没反应时,可能是令牌有问题. form中添加: {{csrf_token()}} ajax中添加: data: {'page': page, '_token' ...
- python学习笔记(十二)之函数
牛刀小试: 定义一个无参函数 >>> def myFirstFunc(): ... print("Hello python") ... print("h ...
- web上下文监听器ServletContextListener
1 package com.liveyc.common.listener; import javax.servlet.ServletContextEvent; import javax.servlet ...
- NYOJ 231 Apple Tree (树状数组)
题目链接 描述 There is an apple tree outside of kaka's house. Every autumn, a lot of apples will grow in t ...
- 回溯算法_01背包问题_Java实现
原文地址:http://blog.csdn.net/ljmingcom304/article/details/50314839 本文出自:[梁敬明的博客] 1.回溯算法 回溯算法也叫试探法,通俗的将就 ...
- 笔记本自开wifi设置
笔记本自开wifi设置 是这样的有些笔记本他自身就可以放出热点供其他的小伙伴们连接,不用非得去下专门的工具有些笔记本的网卡是自带支持双收发的(这里注意我指的是有些笔记本不是全部) 命令我已经写出来了 ...