从Hadoop到S3的distcp失败,"No space available in any of the local directories"



我正在尝试使用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

我们遇到了类似的例外,同时试图直接保存从Apache Spark(版本1.5.2)到S3的运行结果。例外是一样的。我不太确定什么是核心问题 - S3上传似乎并没有与Hadoop的LocalDirallocator类(2.7版)"播放"。

最终为我们解决的问题是:

的组合
  1. 通过将" fs.s3a.fast.upload"设置为hadoop配置中的" true"来启用S3的"快速上传"。这使用S3AfastOutputStream代替S3AOutputStream,直接从内存上传数据,而不是首先分配本地存储

  2. 在保存到S3之前将作业的结果合并到一个零件(在Spark中称为重新分配/合并)

一些警告:

  1. S3的快速上传显然在Hadoop 2.7

  2. 中标记为"实验性"
  3. 此工作范围仅适用于较新的S3A文件系统(" S3A://...")。它对较旧的"本机" S3N文件系统(" S3N://...")

  4. 不起作用

希望这有帮助

理想情况下,您应该使用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 = true

这避免在本地磁盘上缓冲数据,并且实际上也应该更快。

S3N缓冲区目录参数应为:

fs.s3.buffer.dir

因此,如果您坚持使用S3N,请确保它具有足够的空间,并希望解决此问题。

我有几天的错误,没有得到发生的事情,所有节点都有足够的空间(约400GB)。经过一些研究,我发现了这一点:2019-01-09 17:31:31:30,326 warn [main] org.apache.hadoop.fs.fs.localdirallalcator $ sallocatorPercontext:无法创建/mnt/mnt/hadoop/hadoop/tmp/s3a

例外说明了空间,但真正的错误是许可,可以改进消息。

我使用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 Off-aeap内存。

  2. 数组被缓冲到JVM上的内存内存。

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

在上面链接的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")

相关内容

  • 没有找到相关文章

最新更新