如何用AVRO org.apache.avro.mapreduce接口编程?

时间:2013-10-02 10:40:15

标签: hadoop mapreduce avro

我的所有程序都使用hadoop的新MR1接口(org.apache.hadoop.mapreduce)编写,所以我也想使用avro的新org.apache.avro.mapreduce。但它对我不起作用。

程序接收avro数据的输入并输出相同的数据。 我的程序背后的主要思想是将hadoop的Mapper和Reducer子类化为avro包装的键/值。 这是我的工作司机的一块:

    AvroJob.setInputKeySchema(job, NetflowRecord.getClassSchema());
    AvroJob.setOutputKeySchema(job, NetflowRecord.getClassSchema());

    job.setMapperClass(MyAvroMap.class);
    job.setReducerClass(MyAvroReduce.class);

    job.setInputFormatClass(AvroKeyInputFormat.class);
    job.setOutputFormatClass(AvroKeyOutputFormat.class);

    job.setMapOutputKeyClass(AvroKey.class);
    job.setMapOutputValueClass(AvroValue.class);

    job.setOutputKeyClass(AvroKey.class);
    job.setOutputValueClass(NullWritable.class);

MyAvroMap和MyAvroReduce子类的定义分别是

public static class MyAvroMap extends Mapper<AvroKey<NetflowRecord>, NullWritable,
            AvroKey<CharSequence>, AvroValue<NetflowRecord>>{ ... }

public static class MyAvroReduce extends Reducer<AvroKey<CharSequence>, AvroValue<NetflowRecord>, 
                AvroKey<NetflowRecord>, NullWritable>{ ... }

有效的NetflowRecord是我的avro记录类。我得到了运行异常

java.lang.ClassCastException: class org.apache.avro.hadoop.io.AvroKey

通过阅读hadoop和avro的源代码, 我发现JobConf抛出异常以确保 map key是WritableComparable的子类,如下所示(hadoop1.2.1,line759)

WritableComparator.get(getMapOutputKeyClass().asSubclass(WritableComparable.class));

但avro显示AvroKey和AvroValue只是一个简单的包装器没有子类化hadoop的Writable *接口。

我相信,即使没有测试,我也可以使用旧的mapred接口,但它不是我想要的。 你能给我一些关于用纯org.apache.avro.mapreduce接口编程的例子或解释吗?

此致

贾敏

1 个答案:

答案 0 :(得分:5)

经过艰苦搜索,借助此补丁https://issues.apache.org/jira/browse/AVRO-593, 我发现每个AvroKey和AvroValue包装器必须在作业配置中具有模式定义。 这就是我错过的。

这里我有两个选择:

  1. 如果MyAvroMap和MyAvroReduce保持不变,我必须为CharSequence定义一个模式,并使用AvroJob为Mapper输出声明此模式,例如

    AvroJob.setMapOutputKeySchema(job,&lt;“defined-schema-for-charsequence”&gt;); AvroJob.setMapOutputValueSchema(job,NetflowRecord.getClassSchema());

  2. 通过将Mapper输出键/值更改为Text / AvroValue,我只需要为Mapper输出值添加模式声明,例如

    job.setMapOutputKeyClass(Text.class); AvroJob.setMapOutputValueSchema(job,NetflowRecord.getClassSchema());

  3. 使用mapreduce API,我们不再需要继承AvroMapper和AvroReducer。 在这里,我在代码中实现了没有附加模式定义的option2。

    贾敏