【问题标题】:spark scala avro write fails with AbstractMethodErrorspark scala avro 写入失败并出现 AbstractMethodError
【发布时间】:2019-12-05 02:36:04
【问题描述】:

我试图从 avro 读取数据,按字段重新分区数据并将其保存为 avro 格式。下面是我的示例代码。在调试过程中,我无法在我的数据帧上执行 show(10)。它失败并出现以下错误。有人可以帮我理解我在我的代码行中做错了什么吗?

代码:

import org.apache.spark.sql.avro._

val df = spark.read.format("avro").load("s3://test-bucekt/source.avro")

df.show(10)
df.write.partitionBy("partitioning_column").format("avro").save("s3://test-bucket/processed/processed.avro")

显示和写入都失败并出现以下错误:

java.lang.AbstractMethodError: org.apache.spark.sql.avro.AvroFileFormat.shouldPrefetchData(Lorg/apache/spark/sql/SparkSession;Lorg/apache/spark/sql/types/StructType;Lorg/apache/spark/sql/types/StructType;)Z
  at org.apache.spark.sql.execution.FileSourceScanExec.inputRDD$lzycompute(DataSourceScanExec.scala:309)
  at org.apache.spark.sql.execution.FileSourceScanExec.inputRDD(DataSourceScanExec.scala:305)
  at org.apache.spark.sql.execution.FileSourceScanExec.doExecute(DataSourceScanExec.scala:404)
  at org.apache.spark.sql.execution.SparkPlan$$anonfun$execute$1.apply(SparkPlan.scala:131)
  at org.apache.spark.sql.execution.SparkPlan$$anonfun$execute$1.apply(SparkPlan.scala:127)
  at org.apache.spark.sql.execution.SparkPlan$$anonfun$executeQuery$1.apply(SparkPlan.scala:156)
  at org.apache.spark.rdd.RDDOperationScope$.withScope(RDDOperationScope.scala:151)
  at org.apache.spark.sql.execution.SparkPlan.executeQuery(SparkPlan.scala:152)
  at org.apache.spark.sql.execution.SparkPlan.execute(SparkPlan.scala:127)
  at org.apache.spark.sql.execution.ProjectExec.doExecute(basicPhysicalOperators.scala:70)
  at org.apache.spark.sql.execution.SparkPlan$$anonfun$execute$1.apply(SparkPlan.scala:131)
  at org.apache.spark.sql.execution.SparkPlan$$anonfun$execute$1.apply(SparkPlan.scala:127)
  at org.apache.spark.sql.execution.SparkPlan$$anonfun$executeQuery$1.apply(SparkPlan.scala:156)
  at org.apache.spark.rdd.RDDOperationScope$.withScope(RDDOperationScope.scala:151)
  at org.apache.spark.sql.execution.SparkPlan.executeQuery(SparkPlan.scala:152)
  at org.apache.spark.sql.execution.SparkPlan.execute(SparkPlan.scala:127)
  at org.apache.spark.sql.execution.SparkPlan.getByteArrayRdd(SparkPlan.scala:283)
  at org.apache.spark.sql.execution.SparkPlan.executeTake(SparkPlan.scala:375)
  at org.apache.spark.sql.execution.CollectLimitExec.executeCollect(limit.scala:38)
  at org.apache.spark.sql.Dataset.org$apache$spark$sql$Dataset$$collectFromPlan(Dataset.scala:3389)
  at org.apache.spark.sql.Dataset$$anonfun$head$1.apply(Dataset.scala:2550)
  at org.apache.spark.sql.Dataset$$anonfun$head$1.apply(Dataset.scala:2550)
  at org.apache.spark.sql.Dataset$$anonfun$52.apply(Dataset.scala:3370)
  at org.apache.spark.sql.execution.SQLExecution$$anonfun$withNewExecutionId$1.apply(SQLExecution.scala:78)
  at org.apache.spark.sql.execution.SQLExecution$.withSQLConfPropagated(SQLExecution.scala:125)
  at org.apache.spark.sql.execution.SQLExecution$.withNewExecutionId(SQLExecution.scala:73)
  at org.apache.spark.sql.Dataset.withAction(Dataset.scala:3369)
  at org.apache.spark.sql.Dataset.head(Dataset.scala:2550)
  at org.apache.spark.sql.Dataset.take(Dataset.scala:2764)
  at org.apache.spark.sql.Dataset.getRows(Dataset.scala:254)
  at org.apache.spark.sql.Dataset.showString(Dataset.scala:291)
  at org.apache.spark.sql.Dataset.show(Dataset.scala:751)
  at org.apache.spark.sql.Dataset.show(Dataset.scala:710)
  at org.apache.spark.sql.Dataset.show(Dataset.scala:719)
  ... 85 elided

【问题讨论】:

    标签: scala apache-spark


    【解决方案1】:

    这是由于 emr-5.28.0 中对 FileFormat 的意外二进制不兼容更改导致的,该更改将在 emr-5.29.0 发布时修复。幸运的是,对于 Avro 格式,有一个可以在 emr-5.28.0 中使用的简单解决方法。如果您使用与 EMR 捆绑在一起的 spark-avro jar,它会工作,而不是使用 Maven Central 的 spark-avro 版本。也就是说,不要使用--packages org.apache.spark:spark-avro_2.11:2.4.4,而是使用--jars /usr/lib/spark/external/lib/spark-avro.jar。

    【讨论】:

    • 使用捆绑的 spark-avro JAR 是一个非常有见地的解决方法! emr-5.27.0 是否受此影响?我认为它也有问题,因为 5.27.0 使用的是 spark-2.4.4。如果您的用例允许,在 5.29.0 发布之前坚持使用 emr-5.26.0 可能更安全。
    • 不,只有 emr-5.28.0 受此影响。该错误专门存在于 emr-5.28.0 中 Spark 2.4.4 之上的 EMR 补丁之一中,而不是 Spark 2.4.4 本身中。
    • 顺便说一句,emr-5.28.1 和 emr-5.29.0 现在都可以使用,并且都有针对此问题的修复程序。请参考docs.aws.amazon.com/emr/latest/ReleaseGuide/emr-release-5x.html。
    【解决方案2】:

    用于 spark 2.4.4 和 scala 2.11.12 的 spark-avro 似乎有问题。降级到 spark 2.4.3 和 scala 2.11.12 就可以了

    【讨论】:

      【解决方案3】:

      这让我有点抓狂,无法从 AWS 获得帮助。最新版本的 Spark 2.4.4 肯定与 Avro 存在问题。降级到 2.4.3 解决了我遇到的问题。

      【讨论】:

        【解决方案4】:

        上述问题是由于 Spark 和 Spark-Avro 的 jar 兼容性。 使用来自 maven Central 的 Spark 和 Avro 的正确依赖项。

        Spark-Avro 包仅从 Spark 2.4.0 版本开始提供。 在 pom.xml 或 build.sbt 中检查您的 Spark 版本

        以下链接提供有关 maven Central 中 Spark Avro 二进制文件的信息: https://mvnrepository.com/artifact/org.apache.spark/spark-avro

        【讨论】:

        • 我在build.sbt 中定义了正确的版本,看起来像 2.4.4。 spark-avro 有一些问题。我将集群降级到 2.4.3 以及 build.sbt 我能够执行 df.select 但是,df.show 仍然失败但出现新的错误消息。 Caused by: org.apache.spark.SparkException: Job aborted due to stage failure: Task 0 in stage 8.0 failed 4 times, most recent failure: Lost task 0.3 in stage 8.0 (TID 29, ip-10-255-50-25.corp.tenablesecurity.com, executor 19): java.lang.ArrayIndexOutOfBoundsException: 2
        • java.lang.ArrayIndexOutOfBoundsException 是不同的异常,因为“抛出以指示使用非法索引访问了数组。索引为负数或大于或等于数组的大小。 "由于不兼容导致的原始异常已修复。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-22
        • 2020-01-01
        • 2018-06-02
        • 2014-01-03
        • 2019-01-21
        相关资源
        最近更新 更多