我正在尝试使用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版)"播放"。
最终为我们解决的问题是:
的组合通过将" fs.s3a.fast.upload"设置为hadoop配置中的" true"来启用S3的"快速上传"。这使用S3AfastOutputStream代替S3AOutputStream,直接从内存上传数据,而不是首先分配本地存储
在保存到S3之前将作业的结果合并到一个零件(在Spark中称为重新分配/合并)
一些警告:
S3的快速上传显然在Hadoop 2.7
中标记为"实验性"此工作范围仅适用于较新的S3A文件系统(" S3A://...")。它对较旧的"本机" S3N文件系统(" S3N://...")
不起作用
希望这有帮助
理想情况下,您应该使用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
设置为:
-
ByteBuffer被缓冲到JVM Off-aeap内存。
-
数组被缓冲到JVM上的内存内存。
-
磁盘[默认]缓冲到本地硬盘。
在上面链接的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")