hadoop mapreduce 学习(-)

本文介绍了Hadoop MapReduce的基本原理及其应用场景,包括如何通过自定义split方法进行数据分块处理,实现reduce任务的定制化分配,以及如何在Eclipse环境中进行本地调试,提升开发效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、学习内容

1.hadoop map的时候split的方法

2.hadoop reduce时候Partition的自定义实现

3.eclipse本地化调试

二、基础回顾

hadoop的mapreduce可以分为两部分,一部分是map,一部分是reduce,map的输出对应的是reduce的输入,以此达到协调工作的目的。Map-Reduce框架的运作完全基于<key,value>对,即数据的输入是一批<key,value>对,生成的结果也是一批<key,value>对,只是有时候它们的类型不一样而已。Key和value的类由于需要支持被序列化(serialize)操作,所以它们必须要实现Writable接口,而且key的类还必须实现WritableComparable接口,使得可以让框架对数据集的执行排序操作。 

一个Map-Reduce任务的执行过程以及数据输入输出的类型如下所示: 

(input)<k1,v1> -> map -> <k2,v2> -> combine -> <k2,v2> -> reduce -> <k3,v3>(output)

三、内容详解

1.hadoop map对数据进行split(分块)的时候,将严格按照大小进行分块,其hadoop默认的分块大小是64MB,我们可以通过修改hadoop-default.xm配置文件进行大小的分块,至于具体要分多少块需要结合实际的项目情况及结合hadoop官方建议的情况做23:00判断。当然,一说到分块,大家可能就会自觉的想到,同一个文件会被分到不同块中,更极端或者说更常见的情况是一行完整的数据被分到不同的块中,这种情况hadoop是怎么处理的呢?首先,hadoop在分块的时候会记住文件的起始位置和偏移量,然后再根据这个计算,举个普通的例子,如一个文件最后一行有一个单词room,很不幸在分块的时候,ro分在了第一个块,om分在了第二个块,当hadoop读取文件的时候会根据记住地一块的ro后的标志位,读取第二块的第一行,但读取第二块的时候就跳过第一行读取,以确保数据的完整性。

2.hadoop reduce时候Partition的自定义实现,指的是我们可以自己实现一些算法,实现reduce任务的客户化分发。实现的时候需要指定reduce任务的个数,

job.setNumReduceTasks(3);3个表示有0、1、2三个任务可供partition选择,一个具体的例子如下:

import java.io.IOException;
import java.util.*;
import java.util.Map.Entry;




import org.apache.hadoop.fs.Path;


import org.apache.hadoop.io.*;


import org.apache.hadoop.mapreduce.*;
import org.apache.hadoop.mapreduce.Mapper.Context;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.mapreduce.lib.partition.TotalOrderPartitioner;


import org.apache.hadoop.util.*;


public class Sort3{
public static class TestPar extends Partitioner<Text, IntWritable>{
@Override
public int getPartition(Text arg0, IntWritable arg1, int arg2) {
// TODO Auto-generated method stub
if(Integer.parseInt(arg0.toString().substring(7)) < 500)
return 0;
else
return 1;
}
}

   public static class Map extends Mapper<LongWritable, Text, Text, IntWritable> {
     private final static IntWritable one = new IntWritable(1);
     private Text word = new Text();


     public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
       String line = value.toString();
       String[] arr = line.split(",");
       
       word.set(arr[0]);
       context.write(word, one);
       
     }
   }


   public static class Reduce extends Reducer<Text, IntWritable, Text, IntWritable> {
     public void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
    int i=0;
    for (IntWritable value : values){
    i++;
    }
  context.write(key, new IntWritable(i));
     }
   }


   public static void main(String[] args) throws Exception {
  Job job = new Job();
job.setJarByClass(Sort3.class);
job.setJobName("Sort2");


FileInputFormat.addInputPath(job, new Path("hdfs://localhost:9000/input/"));
FileOutputFormat.setOutputPath(job, new Path("hdfs://localhost:9000/output/"));
job.setMapperClass(Map.class);
//job.setCombinerClass(Reduce.class);
job.setReducerClass(Reduce.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
job.setNumReduceTasks(3);


job.setPartitionerClass(TestPar.class);

System.exit(job.waitForCompletion(true) ? 0 : 1);
   }
}

3.eclipse的本地调试是指,mapreduce任务可以在操作系统本地文件上运行,一般如果在hadoop 文件系统上运行的话,需要把每个Java文件导出成jar,在后台运行,这样必然会导致开发效率的降低,我们可以搭本地的环境,调试好以后再放到hadoop上运行,搭本地的时候最好把hadoop文件系统停止了。一下是具体例子:

import java.io.IOException;
import java.util.*;
import java.util.Map.Entry;




import org.apache.hadoop.fs.Path;


import org.apache.hadoop.io.*;


import org.apache.hadoop.mapreduce.*;
import org.apache.hadoop.mapreduce.Mapper.Context;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;


import org.apache.hadoop.util.*;


public class debug{

   public static class Map extends Mapper<LongWritable, Text, Text, IntWritable> {
     private final static IntWritable one = new IntWritable(1);
     private Text word = new Text();


     
     public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
       String line = value.toString();
       String[] arr = line.split(",");
       
       word.set(arr[0]);
       context.write(word, one);
     }
   }


   public static class Reduce extends Reducer<Text, IntWritable, Text, IntWritable> {
     public void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
    int i=0;
    for (IntWritable value : values){
    i++;
    }
  context.write(key, new IntWritable(i));
     }
   }


   public static void main(String[] args) throws Exception {
  Job job = new Job();
job.setJarByClass(debug.class);
job.setJobName("CdrStat");
job.getConfiguration().set("mapred.job.tracker", "local");
job.getConfiguration().set("fs.default.name", "local");
FileInputFormat.addInputPath(job, new Path("/home/robby/input/"));
FileOutputFormat.setOutputPath(job, new Path("/home/robby/output/"));
job.setMapperClass(Map.class);
//job.setCombinerClass(Reduce.class);
job.setReducerClass(Reduce.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
job.setNumReduceTasks(2);

System.exit(job.waitForCompletion(true) ? 0 : 1);
   }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值