【问题标题】:Why is my avrokey datum saying it is a Generic Record When I explicitly wrote the data as AvroKey<SpecificRecord>?当我将数据明确写入 AvroKey<SpecificRecord> 时,为什么我的 avrokey 数据说它是通用记录?
【发布时间】:2016-07-29 03:06:51
【问题描述】:

我正在将一个 hadoop 作业的 avro 输出提供给另一个 hadoop 作业。第一个作业只是运行具有以下设置的映射器。如果有任何用处,我的 avsc 文件会定义一个像这样的复合对象:

[
{
"type": "record",
"name": "MySubRecord",
"namespace": "blah",
"fields": [
    {"name": "foobar", "type": ["null","string"], "default":null},
    {"name": "bar","type": ["null","string"], "default":null},
    {"name": "foo","type": ["null","string"], "default":null},
]
},{
"type": "record",
"name": "MyRecord",
"namespace" : "blah",
"fields" : [
       {"name": "ID", "type":["null", "string"], "default":null},
       {"name": "secondID", "type":["null", "string"], "default":null},
       {"name": "subRecordA", "type":["null","blah.MySubRecord"], "default":null},
       {"name": "subRecordB", "type":["null","blah.MySubRecord"], "default":null},
       {"name": "subRecordC", "type":["null","blah.MySubRecord"], "default":null},
       {"name": "subRecordD", "type":["null","blah.MySubRecord"], "default":null},
       {"name": "subRecordE", "type":["null","blah.MySubRecord"], "default":null},
       {"name": "subRecordF", "type":["null","blah.MySubRecord"], "default":null},
       {"name": "subRecordG", "type":["null","blah.MySubRecord"], "default":null},
       {"name": "subRecordH", "type":["null","blah.MySubRecord"], "default":null}
]
}
]

而我的映射器类签名看起来像这样:

public static class MyMapper extends Mapper<LongWritable, Text, AvroKey<MyRecord>, NullWritable>

使用这样的设置方法:

protected void setup(Context context) throws IOException, InterruptedException {
        super.setup(context);
        keyOut = new AvroKey<>();}

映射器代码如下所示

protected void map(LongWritable keyIn, Text valueIn, Context context) throws IOException, InterruptedException {
        MyRecord record;
        record = getMyRecordFunction();
        keyOut.datum(record);
        context.write(keyOut, NullWritable.get());

    }

我在第一份工作中的逻辑看起来不错,因为当我使用命令行 avro-tools jar 将我的输出打印到 json 时,它看起来和我期望的一样。

我的问题发生在我运行第二份工作时。我的第二份工作的映射器具有以下设置:

public static class MySecondJobMapper extends Mapper<AvroKey<MyRecord>, NullWritable, IntWritable, DoubleWritable>

我的问题发生在我的第二份工作中 map 方法的最开始。我的 map 方法如下所示:

protected void map(AvroKey<MyRecord> key, NullWritable value, Context context) throws IOException, InterruptedException {
        MyRecord myRecord = key.datum();
##### some other logic

每次我运行第二个作业时,都会收到以下错误:

    16/07/28 18:24:38 WARN mapred.LocalJobRunner: job_local1682958846_0001
java.lang.Exception: java.lang.ClassCastException: org.apache.avro.generic.GenericData$Record cannot be cast to MyRecord
    at org.apache.hadoop.mapred.LocalJobRunner$Job.runTasks(LocalJobRunner.java:462)
    at org.apache.hadoop.mapred.LocalJobRunner$Job.run(LocalJobRunner.java:522)
Caused by: java.lang.ClassCastException: org.apache.avro.generic.GenericData$Record cannot be cast to MyRecord
    at your.class.path$StatsCalculatorMapper.map(YourSecondJob.java:150)
    at your.class.path$StatsCalculatorMapper.map(YourSecondJob.java:110)
    at org.apache.hadoop.mapreduce.Mapper.run(Mapper.java:145)

【问题讨论】:

    标签: java hadoop avro


    【解决方案1】:

    看起来问题源于我在本地伪分布式环境中进行测试,并且我的 pom.xml 中指定的正确 avro 版本没有被拉入。相反,旧版本的 avro 与this bug 在我没有意识到的情况下被拉进来。一旦我在 EMR 上运行相同的程序,它就可以正常工作,因为使用的是正确版本的 avro。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-17
      • 1970-01-01
      • 2017-10-14
      • 1970-01-01
      • 2020-09-07
      • 2017-10-17
      • 2016-07-16
      • 1970-01-01
      相关资源
      最近更新 更多