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; } }