避免在 S3 中使用 hadoop (EMR) 创建 _$folder$ 键
Posted
技术标签:
【中文标题】避免在 S3 中使用 hadoop (EMR) 创建 _$folder$ 键【英文标题】:Avoid creation of _$folder$ keys in S3 with hadoop (EMR) 【发布时间】:2017-03-18 15:27:25 【问题描述】:我正在 AWS 数据管道中使用 EMR 活动。此 EMR 活动正在 EMR 集群中运行配置单元脚本。它以 dynamo DB 作为输入并将数据存储在 S3 中。
这是 EMR 活动中使用的 EMR 步骤
s3://elasticmapreduce/libs/script-runner/script-runner.jar,s3://elasticmapreduce/libs/hive/hive-script,--run-hive-script,--hive-versions,latest,--args,-f,s3://my-s3-bucket/hive/my_hive_script.q,-d,DYNAMODB_INPUT_TABLE1=MyTable,-d,S3_OUTPUT_BUCKET=#output.directoryPath
在哪里
out.directoryPath 是:
s3://my-s3-bucket/output/#format(@scheduledStartTime,"YYYY-MM-dd")
所以这会在 S3 中创建一个文件夹和一个文件。 (从技术上讲,它创建了两个键 2017-03-18/<some_random_number>
和 2017-03-18_$folder$
)
2017-03-18
2017-03-18_$folder$
如何避免创建这些额外的空_$folder$
文件。
编辑: 我在https://issues.apache.org/jira/browse/HADOOP-10400 中找到了一个解决方案,但我不知道如何在 AWS 数据管道中实现它。
【问题讨论】:
【参考方案1】:EMR 似乎没有提供避免这种情况的方法。
由于 S3 使用键值对存储系统,Hadoop 文件系统通过创建带有“_$folder$”后缀的空文件来实现 S3 中的目录支持。
您可以安全地删除 S3 存储桶中出现的任何带有
<directoryname>_$folder$
后缀的空文件。这些空文件是由 Hadoop 框架在运行时创建的,但 Hadoop 旨在处理数据,即使这些空文件被删除。https://aws.amazon.com/premiumsupport/knowledge-center/emr-s3-empty-files/
它在 Hadoop 源代码中,因此可以修复,但显然它在 EMR 中没有修复。
如果您觉得很聪明,您可以创建一个与 _$folder$ 后缀匹配的 S3 事件通知,并让它触发一个 Lambda 函数以在创建对象后删除它们。
【讨论】:
我在issues.apache.org/jira/browse/HADOOP-10400 找到了一个解决方案,但我不知道如何在 AWS 数据管道中实现它。 @saurabhagarwal 我相信您不能使用 EMR - 这是一项托管服务。【参考方案2】:在写入 s3 存储桶时使用 s3a,它将删除 $folder$。我已经测试过这种胶水。不确定它是否适用于 EMR 集群。
信用:- 有人在 reddit 上回答
from pyspark.sql import SparkSession
spark=SparkSession.builder.getOrCreate()
df=spark.read.format("parquet").load("s3://testingbucket/")
df.write.format("parquet").save("s3a://testingbucket/parttest/")
spark.stop()
【讨论】:
尝试使用胶水 ETL 并按预期工作。非常感谢! 哇...这就是答案! 非常感谢!这个答案应该是被接受的.. 谢谢,在 EMR Hadoop 中为我工作,同时写入 S3。【参考方案3】:在 S3 中无法实际创建一个空文件夹。 S3 是一个对象存储,所以里面的所有东西都是一个对象。
当 Hadoop 将其用作文件系统时,它需要组织这些对象,使其显示为文件系统树,因此它会创建一些特殊的对象来将对象标记为目录。
您只是存储数据文件,但您可以选择将这些数据文件组织到路径中,这创建了一个类似于文件夹的概念用于遍历。
包括 AWS 管理控制台在内的一些工具通过解释对象名称中的 /s 来模拟文件夹。 Amazon S3 控制台支持将文件夹概念作为对象分组的一种方式。 Bucket Explorer 也是如此。
如果您只是不创建文件夹,而是将文件放在您想要的路径中 - 这应该适合您。
您不必在将文件写入 S3 之前创建文件夹,因为 /all/path/including/filename
- 是 S3 存储中的完整密钥。
【讨论】:
“在 S3 中无法实际创建一个空文件夹。” 这不是真的。虽然文件夹确实不存在,但任何键以斜杠结尾的对象都会被控制台解释为文件夹。不幸的是,Hadoop 完全不必要地使用了这种愚蠢的_$folder$
构造,因为它可以只使用/
——当您在控制台中“创建文件夹”时会发生这种情况。
@Michael-sqlbot S3 确实如此,它只有存储桶和密钥。但是有些工具可以通过解释对象名称中的 /s 来模拟文件夹。 Amazon S3 控制台支持将文件夹概念作为对象分组的一种方式。 Bucket Explorer 也是如此。见这里:bucketexplorer.com/documentation/…
Hadoop s3n 客户端出于历史原因使用 $folder$ 标记;我认为最初你不能使用“/”。较新的 S3a 客户端使用“/”;它忽略列表中的 $folder$ 文件。 Amazon EMR 的 S3 连接器是他们自己的代码,它似乎仍然使用 $folder$。他们的决定。
@SteveLoughran 是否有任何链接详细说明从“_$folder$”到“/”的切换?
不是 AFAIK,您可以查看 Hadoop NativeS3FileSystem 代码历史记录【参考方案4】:
在 EMR 引导操作中使用以下脚本来解决此问题。 AWS 提供的补丁
#!/bin/bash
# NOTE: This script replaces the s3-dist-cp RPM on EMR versions 4.6.0+ with s3-dist-cp-2.2.0.
# This is intended to remove the _$folder$ markers when creating the destination prefixes in S3.
set -ex
RPM=bootstrap-actions/s3-dist-cp-2.2.0/s3-dist-cp-2.2.0-1.amzn1.noarch.rpm
LOCAL_DIR=/var/aws/emr/packages/bigtop/s3-dist-cp/noarch
# Get the region from metadata
REGION=$(curl http://169.254.169.254/latest/meta-data/placement/availability-zone/ 2>/dev/null | head -c -1)
# Choose correct bucket for region
if [ $REGION = "us-east-1" ]
then
BUCKET=awssupportdatasvcs.com
else
BUCKET=$REGION.awssupportdatasvcs.com
fi
# Download new RPM
sudo rm $LOCAL_DIR/s3-dist-cp*.rpm
aws s3 cp s3://$BUCKET/$RPM /tmp/
sudo cp /tmp/s3-dist-cp-2.2.0-1.amzn1.noarch.rpm $LOCAL_DIR/
echo Rebuilding Repo
sudo yum install -y createrepo
sudo createrepo --update -o /var/aws/emr/packages/bigtop /var/aws/emr/packages/bigtop
sudo yum clean all
【讨论】:
以上是关于避免在 S3 中使用 hadoop (EMR) 创建 _$folder$ 键的主要内容,如果未能解决你的问题,请参考以下文章
[AWS][大数据][Hadoop] 使用EMR做大数据分析
通过 EMR 写入 s3a 时出现 OutOfMemory 错误