Hadoop ChainMapper的实际使用

Hadoop ChainMapper的实际使用,hadoop,mapreduce,Hadoop,Mapreduce,我在一个程序中实现了ChainMapper,其中有两个映射器和一个reducer。以下是ChainMapper的实现方式代码: 该代码旨在统计单词出现次数,即单词计数 第一个映射器将从输入文本文件中读取该文件,并拆分每个文本并将其存储在上下文中。 第二个映射器将获得1stMapper的输出,并将所有键文本数据转换为小写键文本数据。 小写键文本数据将存储到上下文中。 Reducer将从2ndMapper获取值,相同的键相关值将进入一个Reducer任务。 在Reducer中,我们只是使用给定的键执

我在一个程序中实现了ChainMapper,其中有两个映射器和一个reducer。以下是ChainMapper的实现方式代码:

该代码旨在统计单词出现次数,即单词计数
第一个映射器将从输入文本文件中读取该文件,并拆分每个文本并将其存储在上下文中。 第二个映射器将获得1stMapper的输出,并将所有键文本数据转换为小写键文本数据。 小写键文本数据将存储到上下文中。 Reducer将从2ndMapper获取值,相同的键相关值将进入一个Reducer任务。 在Reducer中,我们只是使用给定的键执行单词计数操作

import java.io.IOException;
import java.util.StringTokenizer;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
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.chain.ChainMapper;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;

//implementing CHAIN MAPREDUCE without using custom format




//SPLIT MAPPER
class SplitMapper extends Mapper<Object,Text,Text,IntWritable>
{
    StringTokenizer xs;
    private IntWritable dummyValue=new IntWritable(1);
    //private String content;
    private String tokens[];
    @Override
    public void map(Object key,Text value,Context context)throws IOException,InterruptedException{
//      xs=new StringTokenizer(value.toString()," ");
//      while(xs.hasMoreTokens())
//      {
//          content=(String)xs.nextToken();
//      }
        tokens=value.toString().split(" ");
        for(String x:tokens)
        {
        context.write(new Text(x), dummyValue);
        }
    }   
}




//UPPER CASE MAPPER
class UpperCaseMapper extends Mapper<Text,IntWritable,Text,IntWritable>
{
    @Override
    public void map(Text key,IntWritable value,Context context)throws IOException,InterruptedException{
        String val=key.toString().toUpperCase();
        Text newKey=new Text(val);
        context.write(newKey, value);
    }
}



//ChainMapReducer
class ChainMapReducer extends Reducer<Text,IntWritable,Text,IntWritable>
{
    private int sum=0;
    @Override
    public void reduce(Text key,Iterable<IntWritable>values,Context context)throws IOException,InterruptedException{
        for(IntWritable value:values)
        {
            sum+=value.get();
        }
        context.write(key, new IntWritable(sum));
    }
}
public class FirstClass extends Configured implements Tool{
    static Configuration cf;
    public int run (String args[])throws IOException,InterruptedException,ClassNotFoundException{
        cf=new Configuration();

        //bypassing the GenericOptionsParser part and directly running into job declaration part
        Job j=Job.getInstance(cf);

        /**************CHAIN MAPPER AREA STARTS********************************/
        Configuration splitMapConfig=new Configuration(false);
        //below we add the 1st mapper class under ChainMapper Class
        ChainMapper.addMapper(j, SplitMapper.class, Object.class, Text.class, Text.class, IntWritable.class, splitMapConfig);

        //configuration for second mapper
        Configuration upperCaseConfig=new Configuration(false);
        //below we add the 2nd mapper that is the lower case mapper to the Chain Mapper class
        ChainMapper.addMapper(j, UpperCaseMapper.class, Text.class, IntWritable.class, Text.class, IntWritable.class, upperCaseConfig);
        /**************CHAIN MAPPER AREA FINISHES********************************/

        //now proceeding with the normal delivery
        j.setJarByClass(FirstClass.class);
        j.setCombinerClass(ChainMapReducer.class);
        j.setOutputKeyClass(Text.class);
        j.setOutputValueClass(IntWritable.class);
        Path p=new Path(args[1]);

        //set the input and output URI
        FileInputFormat.addInputPath(j, new Path(args[0]));
        FileOutputFormat.setOutputPath(j, p);
        p.getFileSystem(cf).delete(p, true);
        return j.waitForCompletion(true)?0:1;
    }
    public static void main(String args[])throws Exception{
        int res=ToolRunner.run(cf, new FirstClass(), args);
        System.exit(res);
    }
}
import java.io.IOException;
导入java.util.StringTokenizer;
导入org.apache.hadoop.conf.Configuration;
导入org.apache.hadoop.conf.Configured;
导入org.apache.hadoop.fs.Path;
导入org.apache.hadoop.io.IntWritable;
导入org.apache.hadoop.io.Text;
导入org.apache.hadoop.mapreduce.Job;
导入org.apache.hadoop.mapreduce.Mapper;
导入org.apache.hadoop.mapreduce.Reducer;
导入org.apache.hadoop.mapreduce.lib.chain.ChainMapper;
导入org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
导入org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
导入org.apache.hadoop.util.Tool;
导入org.apache.hadoop.util.ToolRunner;
//不使用自定义格式实现链MAPREDUCE
//分割映射器
类拆分映射器扩展映射器
{
StringTokenizer xs;
私有IntWritable dummyValue=新的IntWritable(1);
//私有字符串内容;
私有字符串标记[];
@凌驾
公共void映射(对象键、文本值、上下文上下文)引发IOException、InterruptedException{
//xs=新的StringTokenizer(value.toString(),“”);
//而(xs.hasMoreTokens())
//      {
//content=(字符串)xs.nextToken();
//      }
tokens=value.toString().split(“”);
for(字符串x:令牌)
{
编写(新文本(x),dummyValue);
}
}   
}
//大写映射器
类UpperCaseMapper扩展映射器
{
@凌驾
公共void映射(文本键、IntWritable值、上下文上下文)引发IOException、InterruptedException{
字符串val=key.toString().toUpperCase();
Text newKey=新文本(val);
write(newKey,value);
}
}
//链减速机
类ChainMapReducer扩展了Reducer
{
私有整数和=0;
@凌驾
public void reduce(文本键、Iterablevalues、上下文)引发IOException、InterruptedException{
for(可写入值:值)
{
sum+=value.get();
}
write(key,newintwriteable(sum));
}
}
公共类FirstClass扩展配置的实现工具{
静态配置cf;
public int run(字符串args[])抛出IOException、InterruptedException、ClassNotFoundException{
cf=新配置();
//绕过GenericOptions解析器部分,直接运行到作业声明部分
Job j=Job.getInstance(cf);
/**************链映射器区域开始********************************/
配置splitMapConfig=新配置(false);
//下面我们在ChainMapper类下添加第一个mapper类
addMapper(j,SplitMapper.class,Object.class,Text.class,Text.class,intwriteable.class,splitMapConfig);
//第二个映射器的配置
配置upperCaseConfig=新配置(false);
//下面我们将第二个映射器(小写映射器)添加到链映射器类中
addMapper(j,UpperCaseMapper.class,Text.class,intwriteable.class,Text.class,intwriteable.class,upperCaseConfig);
/**************链映射器区域饰面********************************/
//现在开始正常交货
j、 setJarByClass(头等舱、头等舱);
j、 setCombinerClass(ChainMapReducer.class);
j、 setOutputKeyClass(Text.class);
j、 setOutputValueClass(IntWritable.class);
路径p=新路径(args[1]);
//设置输入和输出URI
addInputPath(j,新路径(args[0]);
setOutputPath(j,p);
p、 getFileSystem(cf).delete(p,true);
返回j.waitForCompletion(true)?0:1;
}
公共静态void main(字符串args[])引发异常{
int res=ToolRunner.run(cf,new FirstClass(),args);
系统退出(res);
}
}
现在,我有一个问题。ChainMapper真的能减轻多个MR工作的负担吗?或者任何人都有ChainMapper实际使用的概念和知识吗




谢谢:)

这里需要两个地图绘制员有什么具体原因吗?为什么不在第一个映射器中使用大写字母,并避免第二个映射器的巨大开销?这样你就不必再使用
ChainMapper
了。是的,我本可以按照你在上面的评论中写的那样做,但我正在练习ChainMapper,我只是写了代码,看看我是否能够正确地编码(程序给出了所需的结果)。我本可以将单词Keys转换成大写,并在一个映射器中使用“1”发出它们,但我故意这样做。这就是为什么我需要知道一些实际需要使用链式映射器的用例或示例,这样我就不需要编写这样的代码,这样会产生太多开销。我很清楚开销。请苏格斯!WordCount只是为了测试ChainMapper每当我设计一个MR管道时,我的首要想法总是让它在尽可能少的操作中运行。每一个新的映射器或减速机都是一个巨大的开销,所以我将设计工作以尽量减少我需要的数量。Map->Reduce->Reduce很有用,但是MapReduce很遗憾地缺少了它(虽然在Tez中是可能的),但是我无法想象我会想要Map->Map->Reduce。