Avro MapReduce类型转换异常求助:GenericData$Record无法转为RxAvro
解决AvroParquetInputFormat的ClassCastException问题
我来帮你捋捋这个问题哈,之前我处理过类似的Avro+Parquet的MapReduce坑,这个报错的原因其实很明确:
java.lang.ClassCastException: org.apache.avro.generic.GenericData$Record cannot be cast to com.xxx.yyy.zz.jobs.actions.test.RxAvro
问题根源
Parquet的Avro输入格式默认会把数据解析成通用的GenericRecord对象,而不是你用AvroTools生成的具体RxAvro类。你虽然编译了RxAvro.java,但作业并没有告诉框架“要用这个具体类来反序列化数据”,所以框架返回的还是GenericRecord,强转自然就炸了。
解决方案
只需要两步就能搞定:
给Job配置具体的Avro Schema/类
在你的run方法里,添加一行代码告诉AvroParquetInputFormat要使用RxAvro的Schema来读取数据,这样框架就会自动把Parquet里的Avro数据反序列化为RxAvro对象:// 关键配置:指定RxAvro的Schema AvroParquetInputFormat.setAvroReadSchema(job, RxAvro.getClassSchema());修改后的完整
run方法代码:public int run(final String[] args) throws Exception { Path inputPath = new Path(args[0]); Path outputPath = new Path(args[1]); Configuration conf = super.getConf(); Job job = new Job(conf); job.setJarByClass(AvroParqueMapreduce.class); job.setInputFormatClass(AvroParquetInputFormat.class); // 新增这行,指定用RxAvro的Schema解析数据 AvroParquetInputFormat.setAvroReadSchema(job, RxAvro.getClassSchema()); AvroParquetInputFormat.setInputPaths(job, inputPath); job.setMapperClass(Map.class); job.setMapOutputKeyClass(Text.class); job.setMapOutputValueClass(Text.class); job.setOutputFormatClass(TextOutputFormat.class); FileOutputFormat.setOutputPath(job, outputPath); return job.waitForCompletion(true) ? 0 : 1; }确保RxAvro类在作业Classpath中
- 如果你是用Oozie提交作业,要把包含
RxAvro.class的Jar包放到作业的lib目录,或者用maven/gradle的打包插件(比如shadowJar)把RxAvro和主类打包到同一个Jar里,避免类加载器找不到的问题。 - 检查Oozie的Java Action配置,确保Jar路径正确,没有遗漏依赖。
- 如果你是用Oozie提交作业,要把包含
额外注意事项
- 一定要保证
RxAvro的Schema和Parquet文件里的Avro Schema完全一致(字段名、类型、顺序都不能错),哪怕有一点差异,框架还是会 fallback 到GenericRecord,报错依旧。 - 如果你的Parquet-Avro依赖版本比较新,可能API略有不同,比如用
setReadSchema代替setAvroReadSchema,核心逻辑都是告诉框架用具体类而非通用Record。
内容的提问来源于stack exchange,提问作者Raghavi Ravi
相关产品推荐
相关产品推荐

