Hadoop中的分布式缓存

时间:2020-01-09 10:34:34  来源:igfitidea点击:

在这篇文章中,我们将看到Hadoop中的分布式缓存是什么。

什么是分布式缓存

顾名思义,Hadoop中的分布式缓存是一种缓存,我们可以在其中存储文件(文本,档案,jars等),该文件分布在运行MapReduce作业的映射器和化简器的节点上。这样,就可以为正在运行的地图本地化缓存的文件并减少任务。

在分布式缓存中添加文件的方法

有一个具有相关方法的DistributedCache类,但整个类在Hadoop2中已弃用。我们应该改用Job类中的方法。

  • public void addCacheFile(URI uri)–添加要本地化的文件。

  • public void addCacheArchive(URI uri)–添加要本地化的档案。

  • public void addFileToClassPath(路径文件)–将文件路径添加到当前的类路径条目集中。它将文件也添加到缓存。用此方法添加的文件在添加到类路径时不会解压缩。

  • public void addArchiveToClassPath(Path archive)–将归档路径添加到当前的类路径条目集中。它将存档也添加到缓存中。分发时,归档文件将解压缩并添加到类路径中。

如何使用分布式缓存

为了通过Hadoop中的分布式缓存提供文件。

1如果要通过分布式缓存提供的文件尚不存在,请将其复制到HDFS。
2基于文件类型,使用相关方法将其添加到分布式缓存中。

例如,如果要向分布式缓存中添加文本文件,则可以在驱动程序类中使用以下语句。

job.addCacheFile(new URI("/user/input/test.txt#test"));

如果我们想将一个jar添加到类路径,则可以按照以下步骤进行操作-

job.addFileToClassPath(new Path("/myapp/mylib.jar"));

分布式缓存示例MapReduce代码

这是Avro MapReduce字数示例程序。输出文件是使用Avro架构的Avro数据文件。使用addCacheFile()方法将此Avro模式添加到分布式缓存中,并由映射器和化简器使用。

import java.io.File;
import java.io.IOException;
import java.net.URI;
import org.apache.avro.Schema;
import org.apache.avro.generic.GenericData;
import org.apache.avro.generic.GenericRecord;
import org.apache.avro.mapred.AvroKey;
import org.apache.avro.mapred.AvroValue;
import org.apache.avro.mapreduce.AvroJob;
import org.apache.avro.mapreduce.AvroKeyOutputFormat;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
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.input.TextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;

public class AvroWordCount extends Configured implements Tool{
	
  // Map function
  public static class AvroWordMapper extends Mapper<LongWritable, Text, AvroKey, AvroValue>{
    private Text word = new Text();
    private GenericRecord record;
     
    @Override
    protected void setup(Context context)
        throws IOException, InterruptedException {
      // That's where file stored in distributed cache is used
      Schema AVRO_SCHEMA = new Schema.Parser().parse(new File("./wcschema"));
      record = new GenericData.Record(AVRO_SCHEMA);
    }
    public void map(LongWritable key, Text value, Context context) 
        throws IOException, InterruptedException {
      // Splitting the line on spaces
      String[] stringArr = value.toString().split("\s+");
      for (String str : stringArr) {
        word.set(str);
        // creating Avro record
        record.put("word", str);
        record.put("count", 1);
        context.write(new AvroKey(word), new AvroValue(record));
      }
    }
  }
	
  // Reduce function
  public static class AvroWordReducer extends Reducer<AvroKey, AvroValue,
      AvroKey, NullWritable>{	  
    Schema AVRO_SCHEMA;
    @Override
    protected void setup(Context context) throws IOException, InterruptedException {
      // That's where file stored in distributed cache is used
      AVRO_SCHEMA = new Schema.Parser().parse(new File("./wcschema"));
    }
    public void reduce(AvroKey key, Iterable<AvroValue> values, Context context) 
        throws IOException, InterruptedException {
      int sum = 0;
      for (AvroValue value : values) {
        GenericRecord	record = value.datum();
        sum += (Integer)record.get("count");
      }
      GenericRecord record = new GenericData.Record(AVRO_SCHEMA);
      record.put("word", key.datum());
      record.put("count", sum);
      context.write(new AvroKey(record), NullWritable.get());
    }
  }

  public static void main(String[] args) throws Exception{
    int exitFlag = ToolRunner.run(new AvroWordCount(), args);
    System.exit(exitFlag);
  }
	
  @Override
  public int run(String[] args) throws Exception {
    Configuration conf = new Configuration();
    Job job = Job.getInstance(conf, "AvroWC");
    job.setJarByClass(getClass());
    job.setMapperClass(AvroWordMapper.class);    
    job.setReducerClass(AvroWordReducer.class);
    // Name after the # sign in the file location
    // will be used as the file name in Mapper/Reducer
    job.addCacheFile(new URI("/user/input/wcschema.avsc#wcschema"));
    AvroJob.setMapOutputKeySchema(job, Schema.create(Schema.Type.STRING));
    FileSystem fs = FileSystem.get(conf);
    // Need schema file stored in HDFS here also
    Path path = new Path("/user/input/wcschema.avsc".toString());
    Schema sc = new Schema.Parser().parse((fs.open(path)));
    AvroJob.setMapOutputValueSchema(job, sc);
    AvroJob.setOutputKeySchema(job,	sc);

    job.setInputFormatClass(TextInputFormat.class);
    job.setOutputFormatClass(AvroKeyOutputFormat.class);
    FileInputFormat.addInputPath(job, new Path(args[0]));
    FileOutputFormat.setOutputPath(job, new Path(args[1]));
    return job.waitForCompletion(true) ? 0 : 1;
  }
}