【问题标题】:Spark: LeaseExpiredException while writing large dataframe to parquet filesSpark:将大型数据帧写入镶木地板文件时出现 LeaseExpiredException
【发布时间】:2018-10-16 01:53:25
【问题描述】:

我有一个大型数据框,我正在将其写入 HDFS 中的镶木地板文件。从日志中获取以下异常:

2018-10-15 18:31:32 ERROR Executor:91 - Exception in task 41.0 in stage 0.0 (TID 1321)
org.apache.spark.SparkException: Task failed while writing rows.
    at org.apache.spark.sql.execution.datasources.FileFormatWriter$.org$apache$spark$sql$execution$datasources$FileFormatWriter$$executeTask(FileFormatWriter.scala:285)
    at org.apache.spark.sql.execution.datasources.FileFormatWriter$$anonfun$write$1.apply(FileFormatWriter.scala:197)
    at org.apache.spark.sql.execution.datasources.FileFormatWriter$$anonfun$write$1.apply(FileFormatWriter.scala:196)
    at org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:87)
    at org.apache.spark.scheduler.Task.run(Task.scala:109)
    at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:369)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: org.apache.hadoop.ipc.RemoteException(org.apache.hadoop.hdfs.server.namenode.LeaseExpiredException): No lease on /home/prod_out/20181007/_temporary/0/_temporary/attempt_20181015183108_0000_m_000041_0/part-00041-1185b10b-bcb1-4b7e-b732-dd6f71322b7d-c000.snappy.parquet (inode 33628528083): File does not exist. Holder DFSClient_NONMAPREDUCE_179567941_77 does not have any open files.
    at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.checkLease(FSNamesystem.java:3481)
    at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.analyzeFileState(FSNamesystem.java:3284)
    at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.getNewBlockTargets(FSNamesystem.java:3122)
    at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.getAdditionalBlock(FSNamesystem.java:3082)
    at org.apache.hadoop.hdfs.server.namenode.NameNodeRpcServer.addBlock(NameNodeRpcServer.java:822)
    at org.apache.hadoop.hdfs.protocolPB.ClientNamenodeProtocolServerSideTranslatorPB.addBlock(ClientNamenodeProtocolServerSideTranslatorPB.java:500)
    at org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos$ClientNamenodeProtocol$2.callBlockingMethod(ClientNamenodeProtocolProtos.java)
    at org.apache.hadoop.ipc.ProtobufRpcEngine$Server$ProtoBufRpcInvoker.call(ProtobufRpcEngine.java:616)
    at org.apache.hadoop.ipc.RPC$Server.call(RPC.java:969)
    at org.apache.hadoop.ipc.Server$Handler$1.run(Server.java:2206)
    at org.apache.hadoop.ipc.Server$Handler$1.run(Server.java:2202)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.security.auth.Subject.doAs(Subject.java:422)
    at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1709)
    at org.apache.hadoop.ipc.Server$Handler.run(Server.java:2200)

    at org.apache.hadoop.ipc.Client.call(Client.java:1475)
    at org.apache.hadoop.ipc.Client.call(Client.java:1412)
    at org.apache.hadoop.ipc.ProtobufRpcEngine$Invoker.invoke(ProtobufRpcEngine.java:229)
    at com.sun.proxy.$Proxy18.addBlock(Unknown Source)
    at org.apache.hadoop.hdfs.protocolPB.ClientNamenodeProtocolTranslatorPB.addBlock(ClientNamenodeProtocolTranslatorPB.java:418)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.hadoop.io.retry.RetryInvocationHandler.invokeMethod(RetryInvocationHandler.java:191)
    at org.apache.hadoop.io.retry.RetryInvocationHandler.invoke(RetryInvocationHandler.java:102)
    at com.sun.proxy.$Proxy19.addBlock(Unknown Source)
    at org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.locateFollowingBlock(DFSOutputStream.java:1455)
    at org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.nextBlockOutputStream(DFSOutputStream.java:1251)
    at org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.run(DFSOutputStream.java:448)
2018-10-15 18:32:06 INFO  CoarseGrainedExecutorBackend:54 - Got assigned task 2189

谷歌搜索,但找不到任何具体的解决方案。将推测设置为假: conf.set("spark.speculation","false")
但仍然没有帮助。 它正在完成几个任务,生成几个零件文件,然后突然停止并出现此错误。

详情: Spark 版本:2.3.1(这在 1.6x 中没有发生)。
只有一个会话在运行,这排除了同一位置被不同会话访问的可能性。

有什么建议吗?

谢谢!

【问题讨论】:

  • “租约”是 HDFS 文件上的写锁。客户端必须向 NameNode 发送心跳来维持租约,否则它最终会过期——并且可以抢占(几秒钟后,以防客户端有故障转移机制,例如 Spark 检查点)然后被完全删除(再过一段时间)。在您的情况下,该文件是作为临时文件创建的,并在租约到期时被删除。
  • 您是否有任何理由让 Spark 执行程序停电并停止写入 HDFS 的时间足够长以至于租约到期?
  • 萨姆森:不确定。相同的代码在 1.6.2 中运行良好,但是当我尝试升级到 2x 时,这种情况正在发生。

标签: scala apache-spark dataframe parquet write-error


【解决方案1】:

实际上问题是因为s​​park在将数据写入指定hdfs位置之前,会将数据上传到临时位置。这两个阶段的机制是用于在处理文件系统时确保最终数据集的一致性。在成功写入的情况下,数据将从临时位置移动。如果写入不成功,数据将从临时位置删除。在您的情况下,可能有不同的执行线程对临时位置进行更改。并且一旦原始执行器线程查看到临时位置,它就不可用并抛出 hdfs 租约异常。 为了避免这个异常,

  1. 确保您没有使用任何并行集合。
  2. 如果适用,请避免使用多线程
  3. spark.conf.set("spark.speculation","false")

【讨论】:

    【解决方案2】:

    这个解决方案可能对你有用:java.lang.OutOfMemoryError: Unable to acquire 100 bytes of memory, got 0

    就我而言,我无法编写 orc 文件。我删除了合并选项,然后它起作用了!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-03-04
      • 1970-01-01
      • 2020-04-02
      • 1970-01-01
      • 2021-03-26
      • 1970-01-01
      • 2019-02-11
      • 2019-06-02
      相关资源
      最近更新 更多