如何在单个MapReduce中读取多种类型的Avro数据

时间:2014-04-23 14:11:13

标签: java hadoop mapreduce cloud avro

我有两种不同类型的Avro数据,它们有一些共同的字段。我想阅读mapper中的那些常见字段。我希望通过在集群中生成单个作业来阅读此内容。

以下是示例avro架构

架构1:

  

{“type”:“record”,“name”:“Test”,“namespace”:“com.abc.schema.SchemaOne”,“doc”:“Avro使用MR存储模式。”,“字段“:[{” Name “:” EE”, “类型”: “串”, “默认”:空},   { “名称”: “AA”, “类型”:[ “空”, “长”], “默认”:空}   { “名称”: “BB”, “类型”:[ “空”, “字符串”], “默认”:空}   { “名称”: “CC”, “类型”:[ “空”, “字符串”], “默认”:空}]}

架构2:

  

{ “类型”: “记录”, “名称”: “测试”, “命名空间”: “com.abc.schema.SchemaTwo”, “文档”:“阿夫罗   使用模式存储   MR “” 田 “:[{” Name “:” EE”, “类型”: “串”, “默认”:空},   { “名称”: “AA”, “类型”:[ “空”, “长”], “默认”:空}   { “名称”: “CC”, “类型”:[ “空”, “字符串”], “默认”:空}   { “名称”: “DD”, “类型”:[ “空”, “字符串”], “默认”:空}]}

驱动程序类:

package com.mango.schema.aggrDaily;

import java.util.Date;
import org.apache.avro.Schema;
import org.apache.avro.mapred.AvroJob;
import org.apache.avro.mapred.Pair;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.mapred.FileInputFormat;
import org.apache.hadoop.mapred.FileOutputFormat;
import org.apache.hadoop.mapred.JobClient;
import org.apache.hadoop.mapred.JobConf;
import org.apache.hadoop.mapred.RunningJob;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;

public class AvroDriver extends Configured implements Tool {

    @Override
    public int run(String[] args) throws Exception {

        JobConf conf = new JobConf(super.getConf(), getClass());
        conf.setJobName("DF");

        args[0] = "hdfs://localhost:9999/home/hadoop/work/alok/aggrDaily/data/avro512MB/part-m-00000.avro";
        args[1] = "/home/hadoop/work/alok/tmp"; // temp location
        args[2] = "hdfs://localhost:9999/home/hadoop/work/alok/tmp/10";

        FileInputFormat.addInputPaths(conf, args[0]);
        FileOutputFormat.setOutputPath(conf, new Path(args[2]));

        AvroJob.setInputReflect(conf);
        AvroJob.setMapperClass(conf, AvroMapper.class);

        AvroJob.setOutputSchema(
                conf,
                Pair.getPairSchema(Schema.create(Schema.Type.STRING),
                        Schema.create(Schema.Type.INT)));

        RunningJob job = JobClient.runJob(conf);

        return 0;
    }

    public static void main(String[] args) throws Exception {
        long startTime = new Date().getTime();
        System.out.println("Start Time :::::" + startTime);
        Configuration conf = new Configuration();
        int exitCode = ToolRunner.run(conf, new AvroDriver(), args);
        long endTime = new Date().getTime();
        System.out.println("End Time :::::" + endTime);
        System.out.println("Total Time Taken:::"
                + new Double((endTime - startTime) * 0.001) + "Sec.");
        System.exit(exitCode);
    }
}

Mapper类:

package com.mango.schema.aggrDaily;

import java.io.IOException;
import org.apache.avro.generic.GenericData;
import org.apache.avro.mapred.AvroCollector;
import org.apache.avro.mapred.AvroMapper;
import org.apache.avro.mapred.Pair;
import org.apache.hadoop.mapred.Reporter;

public class AvroMapper extends
        AvroMapper<GenericData, Pair<CharSequence, Integer>> {

    @Override
    public void map(GenericData record,
        AvroCollector<Pair<CharSequence, Integer>> collector, Reporter reporter) throws IOException {
        System.out.println("record :: " + record);
    }

}

我可以通过设置输入架构来读取此代码的Avro数据。

AvroJob.setInputSchema(conf, new AggrDaily().getSchema());

由于Avro数据已在数据中构建了架构,因此我不希望将特定架构明确传递给作业。我在Pig中实现了这一点。但现在我想在MapReduce中实现相同的目标。

有人可以通过MR代码帮助我实现这个目标,还是让我知道我哪里出错?

2 个答案:

答案 0 :(得分:0)

通过* org.apache.hadoop.mapreduce.lib.input。 MultipleInputs 类,我们可以通过单个MR作业读取多个avro数据

答案 1 :(得分:0)

我们不能使用org.apache.hadoop.mapreduce.lib.input.MultipleInputs来读取多个avro数据,因为每个avro输入都有一个与之关联的模式,当前上下文只能存储其中一个模式。投入。所以其他映射器将无法读取数据..

同样的事情也适用于HCatInputFormat(因为每个输入都有一个与之关联的模式)。然而,在Hcatalog 0.14以后,有相同的规定。

AvroMultipleInputs可用于实现相同目的。它仅适用于Specific和Reflect映射。它从版本1.7.7开始提供。