Избегайте создания ключей _$folder$ в S3 с помощью hadoop (EMR)

Я использую EMR Activity в конвейере данных AWS. Это действие EMR выполняет сценарий куста в кластере EMR. Он принимает динамо DB в качестве входных данных и сохраняет данные в S3.

Это шаг EMR, используемый в EMR Activity

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.direcoryPath - это:

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.

5 ответов

Решение

EMR, кажется, не предоставляет способ избежать этого.

Поскольку S3 использует систему хранения пар ключ-значение, файловая система Hadoop реализует поддержку каталогов в S3, создавая пустые файлы с суффиксом "_$folder$".

Вы можете безопасно удалить любые пустые файлы с помощью <directoryname>_$folder$ суффикс, который появляется в ваших корзинах S3. Эти пустые файлы создаются платформой Hadoop во время выполнения, но Hadoop предназначен для обработки данных, даже если эти пустые файлы удалены.

https://aws.amazon.com/premiumsupport/knowledge-center/emr-s3-empty-files/

Он находится в исходном коде Hadoop, поэтому его можно исправить, но, очевидно, он не исправлен в EMR.

Если вы чувствуете себя умным, вы можете создать уведомление о событии S3, соответствующее суффиксу _ $ folder $, и заставить его запускать функцию Lambda для удаления объектов после их создания.

Используйте s3a при записи в ведро s3, он удалит $ 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()

В S3 нет способа создать пустую папку. S3 - это хранилище объектов, поэтому там есть все объекты. Когда Hadoop использует его в качестве файловой системы, ему необходимо организовать эти объекты таким образом, чтобы он отображался в виде дерева файловой системы, поэтому он создает некоторые специальные объекты, чтобы пометить объект как каталог. Вы просто храните файлы данных, но вы можете организовать эти файлы данных в пути, что создает концепцию, аналогичную папкам для обхода.

Если вы просто не создаете папку, а размещаете файлы по нужному пути - это должно работать для вас. Вам не нужно создавать папку перед записью файлов в S3.

Также это может помочь: https://qubole.zendesk.com/hc/en-us/articles/213496246-How-To-Remove-Dir-marker-folders-in-S3-NativeFS-

Вместо использования s3:// используйте s3a://, чтобы решить вашу проблему.

Это происходит из-за пути S3, который вы используете во время записи.

s3:// против s3a://

s3:// создаст папку s3a:// не будет

Префиксы и используются для указания протокола доступа к данным, хранящимся в Amazon S3, в Apache Spark.

  1. : этот префикс используется для указания протокола S3 для доступа к данным в Spark. Это протокол по умолчанию, используемый Spark, который обеспечивает базовые функции для чтения и записи данных из S3 и в него. При использовании Spark использует соединитель Hadoop S3A для взаимодействия с S3.

  2. : этот префикс также используется для указания протокола S3 для доступа к данным в Spark. Это альтернативный протокол, который предоставляет дополнительные функции и оптимизации по сравнению с . При использовании Spark использует разъем Hadoop S3A, который является улучшенной версией разъема S3.

В целом рекомендуется использовать вместо Spark и S3 при работе, так как обеспечивает лучшую производительность и надежность. Однако конкретный выбор между и может зависеть от вашего конкретного варианта использования и требований.

Например, чтобы указать путь ввода или вывода для чтения или записи данных в S3 с помощью , вы можете использовать следующий синтаксис:

      inputPath = "s3://your-bucket/your-input-path"
outputPath = "s3://your-bucket/your-output-path"

Аналогично, чтобы использовать, вы можете заменитьсв пути:

      inputPath = "s3a://your-bucket/your-input-path"
outputPath = "s3a://your-bucket/your-output-path"

Используйте сценарий ниже в действии начальной загрузки 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
Другие вопросы по тегам