Hadoop-MapReduce-CombineTextInputFormat,KeyValueTextInputFormat,NLineInputFormat,自定义InputFormat

CombineTextInputFormat

    Hadoop默认的TextInputFormat切片机制是对任务按文件切片,不管文件多小,都会是一个单独的切片,然后交给一个MapTask。如果有大量小文件,就会产生大量MapTask,处理效率非常低。
    CombineTextInputFormat用于处理大量小文件,它可以将多个小文件从逻辑上看成一个切片。多个小文件可以交给一个MapTask处理。
虚拟存储过程
    setMaxInputSplitSize设置最大切片大小,假设4M。
    如果文件大小小于最大切片大小,则单独划分为一块,如一个2.5M的文件划分为一块。
    如果文件大小大于最大切片大小但小于最大切片大小的两倍,则平分为两块(防止出现太小切片),如5M划分两块,各2.5M。
    如果文件大小大于最大切片大小的两倍,则以最大值切一块。
    例如setMaxInputSplitSize值为4M,输入文件大小为8.02M,则先逻辑上分成一个4M,剩余的大小为4.02M。如果按照4M逻辑划分,就会出现0.02M的小的虚拟存储文件,所以将剩余的4.02M文件切分成(2.01M和2.01M)两个文件。
切片过程
    判断虚拟存储的文件大小是否大于setMaxInputSplitSize值,大于等于则单独形成一个切片。
    如果不大于,则跟下一个虚拟存储文件进行合并,形成一个切片。如两个文件,1.5M和3M,形成一个4.5M的切片。

    在驱动类添加如下代码,采用CombineTextInputFormat。

// 如果不设置InputFormat,它默认用的是TextInputFormat.class
job.setInputFormatClass(CombineTextInputFormat.class);

//虚拟存储切片最大值设置4m
CombineTextInputFormat.setMaxInputSplitSize(job, 4194304);

KeyValueTextInputFormat

    每一行被分割符(第一个分隔符)分割为key,value。可以通过在驱动类设置 conf.set(KeyValueLineRecordReader.KEY_VALUE_SEPERATOR, “\t”) 来设定分割符,默认分割符是 tab("\t")。

    在驱动类添加如下代码,采用KeyValueTextInputFormat。

//设定分割符,默认分割符是\t
conf.set(KeyValueLineRecordReader.KEY_VALUE_SEPERATOR, " ");

// 如果不设置InputFormat,它默认用的是TextInputFormat.class
job.setInputFormatClass(KeyValueTextInputFormat.class);

NLineInputFormat

    每个MapTask处理的InputSplit不再按block块进行划分,而是按指定的行数N来划分。即输入文件的总行数 ÷ N = 切片数,如果不整除,切片数=商+1。.

    在驱动类添加如下代码,采用NLineInputFormat。

//设定分割符,默认分割符是\t
NLineInputFormat.setNumLinesPerSplit(job, 3);

// 如果不设置InputFormat,它默认用的是TextInputFormat.class
job.setInputFormatClass(NLineInputFormat.class);

自定义InputFormat

    自定义InputFormat,将多个小文件合并成一个SequenceFile文件(SequenceFile文件是Hadoop用来存储二进制形式的key-value对的文件格式),SequenceFile里面存储着多个文件,key为文件路径+名称为,value为文件内容。
    自定义一个类继承FileInputFormat,重写createRecordReader(),创建自定义的RecordReader对象,并初始化initialize。

import java.io.IOException;
import org.apache.hadoop.io.BytesWritable;
import org.apache.hadoop.io.Text;
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.FileInputFormat;

public class DIYInputFormat extends FileInputFormat<Text, BytesWritable>{
	@Override
	public RecordReader<Text, BytesWritable> createRecordReader(InputSplit split, TaskAttemptContext context)
			throws IOException, InterruptedException {
		DIYRecordReader reader = new DIYRecordReader();
		reader.initialize(split, context);
		return reader;
	}
}

    键是文件的全路径,值是文件内容。nextKeyValue()在Mapper.run()方法调用,每个切片会新创建一个DIYRecordReader对象。

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.Text;
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 DIYRecordReader extends RecordReader<Text, BytesWritable>{

	FileSplit split;
	Configuration conf;
	Text key = new Text();
	BytesWritable value = new BytesWritable();
	boolean isProgress = true;
	
	@Override
	public void initialize(InputSplit split, TaskAttemptContext context) throws IOException, InterruptedException {
		this.split = (FileSplit) split;
		this.conf = context.getConfiguration();
	}

	@Override
	public boolean nextKeyValue() throws IOException, InterruptedException {
		if (isProgress) {
			//1.获取fs对象
			Path path = split.getPath();
			FileSystem fs = path.getFileSystem(conf);
			//2.获取输入流
			FSDataInputStream fis = fs.open(path);
			//3.拷贝
			byte[] buf = new byte[(int) split.getLength()];
			IOUtils.readFully(fis, buf, 0, buf.length);
			//4.封装key
			key.set(path.toString());
			//5.封装value
			value.set(buf, 0, buf.length);
			//6.关闭资源
			IOUtils.closeStream(fis);
			isProgress = false;
			return true;
		}
		return false;
	}

	@Override
	public Text getCurrentKey() throws IOException, InterruptedException {
		return key;
	}

	@Override
	public BytesWritable getCurrentValue() throws IOException, InterruptedException {
		return value;
	}

	@Override
	public float getProgress() throws IOException, InterruptedException {
		return 0;
	}

	@Override
	public void close() throws IOException {}
}
import java.io.IOException;
import org.apache.hadoop.io.BytesWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;

public class DIYInputFormatMapper extends Mapper<Text, BytesWritable, Text, BytesWritable> {
	@Override
	protected void map(Text key, BytesWritable value, Mapper<Text, BytesWritable, Text, BytesWritable>.Context context)
			throws IOException, InterruptedException {
		context.write(key, value);
	}
}
import java.io.IOException;
import org.apache.hadoop.io.BytesWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;

public class DIYInputFormatReducer extends Reducer<Text, BytesWritable, Text, BytesWritable> {
	@Override
	protected void reduce(Text key, Iterable<BytesWritable> values,
			Reducer<Text, BytesWritable, Text, BytesWritable>.Context context) throws IOException, InterruptedException {
		for (BytesWritable value : values) {
			context.write(key, value);
		}
	}
}

    驱动类设置InputFormat为自定义的InputFormat。设置OutputFormat为SequenceFileOutputFormat,多个文件输出成一个文件,键为全路径,值为文件内容,访问时输入全路径即可获得内容。

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.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.mapreduce.lib.output.SequenceFileOutputFormat;

public class DIYInputFormatDriver {
	public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
		args = new String[] { "e:/input", "e:/output"};
		Configuration conf = new Configuration();
		Job job = Job.getInstance(conf);
		job.setJarByClass(DIYInputFormatDriver.class);
		job.setMapperClass(DIYInputFormatMapper.class);
		job.setReducerClass(DIYInputFormatReducer.class);
		job.setMapOutputKeyClass(Text.class);
		job.setMapOutputValueClass(BytesWritable.class);
		job.setOutputKeyClass(Text.class);
		job.setOutputValueClass(BytesWritable.class);
		FileInputFormat.setInputPaths(job, new Path(args[0]));
		FileOutputFormat.setOutputPath(job, new Path(args[1]));
		//设置输入的InputFormat
		job.setInputFormatClass(DIYInputFormat.class);
		//设置输出的OutputFormat
		job.setOutputFormatClass(SequenceFileOutputFormat.class);
		boolean result = job.waitForCompletion(true);
		System.exit(result ? 0 : 1);
	}
}

InputFormat总结

 <K, V>切片
TextInputFormat(默认)键是存储该行在整个文件中的起始字节偏移量,LongWritable类型。
值是该行的内容,不包括任何行终止符(换行符和回车键),Text类型。
按块的大小切片,本地是32M;集群Hadoop1.0是64M;2.0是128M
CombineTextInputFormat键和值与TextInputFormat一样按给定大小切片
KeyValueTextInputFormat键是该行第一个分隔符左边的内容。
值是该行第一个分隔符右边的内容。
按块的大小切片
NLineInputFormat键和值与TextInputFormat一样按指定数量的行切块片*自定义InputFormat**

    

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
hadoop-mapreduce-client-core是Hadoop分布式计算框架中的核心模块之一。它主要包含了Hadoop MapReduce的核心功能和API接口,是实现MapReduce编程模型的必备组件。 Hadoop MapReduce是一种用于大规模数据处理的编程模型,其核心思想是将大规模数据集分解成多个较小的数据块,分别在集群中的不同机器上进处理,最后将结果整合。hadoop-mapreduce-client-core模块提供了与MapReduce相关的类和方法,方便开发者实现自定义的Map和Reduce任务。 具体来说,hadoop-mapreduce-client-core模块包含了以下重要组件和功能: 1. Job:Job表示一个MapReduce任务的定义和描述,包括输入路径、输出路径、Mapper和Reducer等。 2. Mapper:Mapper是MapReduce任务中的映射函数,它负责将输入数据转换成<key, value>键值对的形式。 3. Reducer:Reducer是MapReduce任务中的归约函数,它按照相同的key将所有Mapper输出的value聚合处理。 4. InputFormatInputFormat负责将输入数据切分成多个InputSplit,每个InputSplit由一个Mapper负责处理。 5. OutputFormat:OutputFormat负责将Reducer的输出结果写入指定的输出路径中。 使用hadoop-mapreduce-client-core模块,开发者可以基于Hadoop分布式计算框架快速开发并处理大规模数据的应用程序。通过编写自定义的Mapper和Reducer,可以实现各种类型的分布式计算,如数据清洗、聚合分析、机器学习等。 总之,hadoop-mapreduce-client-core是Hadoop分布式计算框架中的核心模块,提供了实现MapReduce编程模型所需的基本功能和API接口。使用该模块,开发者可以利用Hadoop的分布式计算能力,高效地处理和分析大规模数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值