Hadoop是一个开源的分布式计算框架,用于处理大规模数据集。在Hadoop中,数据被分成多个块,这些块被称为HDFS块(Hadoop分布式文件系统块)。HDFS块是Hadoop中的最小数据单元,它用于实现数据的分布式存储和处理。
Hadoop的数据分割是通过InputFormat和RecordReader来实现的。InputFormat用于将输入数据划分为数据块,而RecordReader则将这些数据块转换为可供处理的记录。
下面是Hadoop数据分割的详细流程:
-
输入数据分割:
- Hadoop将输入数据按照一定的规则进行分割,这个规则由InputFormat定义。Hadoop提供了多种InputFormat,例如TextInputFormat、KeyValueTextInputFormat等。
- 以TextInputFormat为例,它将输入数据按照换行符进行分割,每行作为一个数据块。
- 用户也可以自定义InputFormat来实现特定的数据分割方式。
-
分割处理:
- Hadoop将分割后的数据块交给不同的计算节点进行处理。
- 每个计算节点上都有一个TaskTracker,它负责执行任务并处理数据块。
- TaskTracker会将数据块加载到内存中,并通过RecordReader将数据块转换为可处理的记录。
-
数据记录转换:
- RecordReader是Hadoop用于将数据块转换为记录的组件。
- RecordReader读取数据块,并将数据块分解为记录,每个记录包含一个键和一个值。
- 以TextInputFormat为例,它将每行数据作为一个记录,键为行号,值为行内容。
-
记录处理:
- Hadoop将每个记录交给用户自定义的Map函数进行处理。
- Map函数是Hadoop的分布式计算模型中的一个重要组件,它负责将输入记录转换为键值对的形式,并输出中间结果。
- 用户可以根据实际需求自定义Map函数。
-
中间结果汇总:
- Hadoop会对Map函数的输出结果进行合并,并进行排序。
- 这些中间结果将作为输入传递给Reduce函数。
-
Reduce处理:
- Reduce函数是Hadoop的分布式计算模型中的另一个重要组件,它负责将中间结果进行汇总和处理,生成最终的输出结果。
- 用户可以根据实际需求自定义Reduce函数。
-
输出结果:
- Hadoop将Reduce函数的输出结果写入输出文件系统,用户可以对结果进行进一步的处理或分析。
示例代码如下:
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
public class WordCount {
public static class TokenizerMapper
extends Mapper<LongWritable, Text, Text, LongWritable> {
private final static LongWritable one = new LongWritable(1);
private Text word = new Text();
public void map(LongWritable key, Text value, Context context)
throws IOException, InterruptedException {
String[] words = value.toString().split(" ");
for (String w : words) {
word.set(w);
context.write(word, one);
}
}
}
public static class IntSumReducer
extends Reducer<Text, LongWritable, Text, LongWritable> {
private LongWritable result = new LongWritable();
public void reduce(Text key, Iterable<LongWritable> values, Context context)
throws IOException, InterruptedException {
long sum = 0;
for (LongWritable val : values) {
sum += val.get();
}
result.set(sum);
context.write(key, result);
}
}
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
Job job = Job.getInstance(conf, "word count");
job.setJarByClass(WordCount.class);
job.setMapperClass(TokenizerMapper.class);
job.setCombinerClass(IntSumReducer.class);
job.setReducerClass(IntSumReducer.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(LongWritable.class);
FileInputFormat.addInputPath(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new