从Hadoop到S3的distcp失败,“任何本地目录中都没有空间”

时间:2016-06-16 20:01:35

标签: hadoop amazon-s3 distcp

我正在尝试使用distcp将数据从本地hadoop群集复制到S3存储桶。

有时它“有效”,但有些映射器失败,下面是堆栈跟踪。其他时候,很多地图选手都失败了,整个工作取消了。

错误“任何本地目录中都没有可用空间”。对我来说没有意义。边缘节点(运行distcp命令的地方),群集和S3存储桶中有大量空间。

任何人都可以对此有所了解吗?

16/06/16 15:48:08 INFO mapreduce.Job: The url to track the job: <url>
16/06/16 15:48:08 INFO tools.DistCp: DistCp job-id: job_1465943812607_0208
16/06/16 15:48:08 INFO mapreduce.Job: Running job: job_1465943812607_0208
16/06/16 15:48:16 INFO mapreduce.Job: Job job_1465943812607_0208 running in uber mode : false
16/06/16 15:48:16 INFO mapreduce.Job:  map 0% reduce 0%
16/06/16 15:48:23 INFO mapreduce.Job:  map 33% reduce 0%
16/06/16 15:48:26 INFO mapreduce.Job: Task Id : attempt_1465943812607_0208_m_000001_0, Status : FAILED
Error: java.io.IOException: File copy failed: hdfs://<hdfs path>/000000_0 --> s3n://<bucket>/<s3 path>/000000_0
        at org.apache.hadoop.tools.mapred.CopyMapper.copyFileWithRetry(CopyMapper.java:285)
        at org.apache.hadoop.tools.mapred.CopyMapper.map(CopyMapper.java:253)
        at org.apache.hadoop.tools.mapred.CopyMapper.map(CopyMapper.java:50)
        at org.apache.hadoop.mapreduce.Mapper.run(Mapper.java:146)
        at org.apache.hadoop.mapred.MapTask.runNewMapper(MapTask.java:787)
        at org.apache.hadoop.mapred.MapTask.run(MapTask.java:341)
        at org.apache.hadoop.mapred.YarnChild$2.run(YarnChild.java:168)
        at java.security.AccessController.doPrivileged(Native Method)
        at javax.security.auth.Subject.doAs(Subject.java:415)
        at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1709)
        at org.apache.hadoop.mapred.YarnChild.main(YarnChild.java:162)
Caused by: java.io.IOException: Couldn't run retriable-command: Copying hdfs://<hdfs path>/000000_0 to s3n://<bucket>/<s3 path>/000000_0
        at org.apache.hadoop.tools.util.RetriableCommand.execute(RetriableCommand.java:101)
        at org.apache.hadoop.tools.mapred.CopyMapper.copyFileWithRetry(CopyMapper.java:281)
        ... 10 more
Caused by: org.apache.hadoop.util.DiskChecker$DiskErrorException: No space available in any of the local directories.
        at org.apache.hadoop.fs.LocalDirAllocator$AllocatorPerContext.getLocalPathForWrite(LocalDirAllocator.java:366)
        at org.apache.hadoop.fs.LocalDirAllocator$AllocatorPerContext.createTmpFileForWrite(LocalDirAllocator.java:416)
        at org.apache.hadoop.fs.LocalDirAllocator.createTmpFileForWrite(LocalDirAllocator.java:198)
        at org.apache.hadoop.fs.s3native.NativeS3FileSystem$NativeS3FsOutputStream.newBackupFile(NativeS3FileSystem.java:263)
        at org.apache.hadoop.fs.s3native.NativeS3FileSystem$NativeS3FsOutputStream.<init>(NativeS3FileSystem.java:245)
        at org.apache.hadoop.fs.s3native.NativeS3FileSystem.create(NativeS3FileSystem.java:412)
        at org.apache.hadoop.fs.FileSystem.create(FileSystem.java:986)
        at org.apache.hadoop.tools.mapred.RetriableFileCopyCommand.copyToFile(RetriableFileCopyCommand.java:174)
        at org.apache.hadoop.tools.mapred.RetriableFileCopyCommand.doCopy(RetriableFileCopyCommand.java:123)
        at org.apache.hadoop.tools.mapred.RetriableFileCopyCommand.doExecute(RetriableFileCopyCommand.java:99)
        at org.apache.hadoop.tools.util.RetriableCommand.execute(RetriableCommand.java:87)
        ... 11 more

4 个答案:

答案 0 :(得分:2)

我们在尝试将Apache Spark(版本1.5.2)的运行结果直接保存到S3时遇到了类似的异常。但例外是相同的。我不确定核心问题是什么 - 不知何故,S3上传似乎并没有“好玩”#34;使用Hadoop的LocalDirAllocator类(版本2.7)。

最终为我们解决的是以下各项的组合:

  1. 启用S3&#34;快速上传&#34; - 通过设置&#34; fs.s3a.fast.upload&#34;到&#34;真&#34;在Hadoop配置中。这使用S3AFastOutputStream而不是S3AOutputStream并直接从内存上传数据,而不是先分配本地存储

  2. 在保存到s3之前将作业结果合并到单个部分(在Spark中称为重新分区/合并)

  3. 但有些警告:

    1. S3的快速上传显然已被标记为&#34;实验&#34;在Hadoop 2.7

    2. 此解决方法仅适用于较新的s3a文件系统(&#34; s3a://...")。它不会为年长的&#34;本地人&#34; s3n文件系统(&#34; s3n://...&#34;)

    3. 希望这会有所帮助

答案 1 :(得分:1)

理想情况下,您应该使用s3a而不是s3n,因为不推荐使用s3n。

使用s3a,有一个参数:

<property>
  <name>fs.s3a.buffer.dir</name>
  <value>${hadoop.tmp.dir}/s3a</value>
  <description>Comma separated list of directories that will be used to buffer file
uploads to. No effect if fs.s3a.fast.upload is true.</description>
</property>

当您收到本地文件错误时,很可能是因为缓冲区目录没有空格。

虽然您可以将此设置更改为指向具有更多空间的目录,但可以设置更好的解决方案(再次在S3a中):

fs.s3a.fast.upload =真

这可以避免缓冲本地磁盘上的数据,实际上也应该更快。

S3n缓冲区目录参数应为:

fs.s3.buffer.dir

因此,如果你坚持使用s3n,请确保它有足够的空间,并且应该有希望解决这个问题。

答案 2 :(得分:0)

我有几天都遇到此错误,但没有得到所发生的一切,所有节点都具有PLENTY空间(大约400GB)。 经过研究,我发现了这一点: 2019-01-09 17:31:30,326警告[main] org.apache.hadoop.fs.LocalDirAllocator $ AllocatorPerContext:无法创建/ mnt / hadoop / tmp / s3a

该异常说明了空间,但真正的错误是权限,该消息可以得到改善。

答案 3 :(得分:0)

使用Hadoop 2.8.5时,我遇到了同样的问题,但是将"fs.s3a.fast.upload"设置为"true"并不能解决问题。我还必须将fs.s3a.fast.upload.buffer设置为"bytebuffer"fs.s3a.fast.upload.buffer的默认设置为"disk",这说明了为什么我仍然遇到相同的错误。还有一个"array"设置,但我没有尝试过。

可用的fs.s3a.fast.upload.buffer设置是:

  1. bytebuffer已缓冲到JVM堆外内存。

  2. array已缓冲到JVM堆内存。

  3. disk [默认]缓冲到本地硬盘。

在上面链接的Hadoop站点上都有每个警告的说明。

下面的pySpark示例代码。

from pyspark.sql import SparkSession

spark = SparkSession.builder.getOrCreate()
sc = spark.sparkContext

hdpConf = sc._jsc.hadoopConfiguration()
user = os.getenv("USER")
hdpConf.set("hadoop.security.credential.provider.path", "jceks://hdfs/user/{}/awskeyfile.jceks".format(user))
hdpConf.set("fs.s3a.fast.upload", "true")
hdpConf.set("fs.s3a.fast.upload.buffer", "bytebuffer")