web-dev-qa-db-fra.com

Temps d'écriture S3 extrêmement lent depuis EMR / Spark

J'écris pour voir si quelqu'un sait comment accélérer les temps d'écriture S3 à partir de Spark en cours d'exécution dans EMR?

My Spark Le travail prend plus de 4 heures pour être terminé, mais le cluster n'est chargé que pendant les 1,5 premières heures.

enter image description here

J'étais curieux de savoir ce que Spark faisait tout ce temps. J'ai regardé les journaux et j'ai trouvé de nombreux s3 mv commandes, une pour chaque fichier. En jetant un coup d'œil directement à S3, je vois que tous mes fichiers sont dans un répertoire _ temporaire .

Secondaire, je suis préoccupé par le coût de mon cluster, il semble que je doive acheter 2 heures de calcul pour cette tâche spécifique. Cependant, je finis par acheter jusqu'à 5 heures. Je suis curieux de savoir si EMR AutoScaling peut aider à réduire les coûts dans cette situation.

Certains articles discutent de la modification de l'algorithme de validation de sortie de fichier, mais j'ai eu peu de succès avec cela.

sc.hadoopConfiguration.set("mapreduce.fileoutputcommitter.algorithm.version", "2")

L'écriture sur le HDFS local est rapide. Je suis curieux de savoir que l'émission d'une commande hadoop pour copier les données vers S3 serait plus rapide?

enter image description here

21
jspooner

Ce que vous voyez est un problème avec outputcommitter et s3. le travail de validation applique fs.rename sur le dossier _temporary et puisque S3 ne prend pas en charge le changement de nom, cela signifie qu'une seule demande copie et supprime maintenant tous les fichiers de _temporary vers sa destination finale.

sc.hadoopConfiguration.set("mapreduce.fileoutputcommitter.algorithm.version", "2") ne fonctionne qu'avec la version hadoop> 2.7. ce qu'il fait est de copier chaque fichier de _temporary sur la tâche de validation et non de valider le travail afin qu'il soit distribué et fonctionne assez rapidement.

Si vous utilisez une ancienne version de hadoop, j'utiliserais Spark 1.6 et utiliser:

sc.hadoopConfiguration.set("spark.sql.parquet.output.committer.class","org.Apache.spark.sql.parquet.DirectParquetOutputCommitter")

* notez que cela ne fonctionne pas avec la spécification activée ou l'écriture en mode ajout

** notez également qu'il est obsolète dans Spark 2.0 (remplacé par algorithm.version = 2)

BTW dans mon équipe, nous écrivons réellement avec Spark vers HDFS et utilisons des travaux DISTCP (spécifiquement s3-dist-cp) en production pour copier les fichiers vers S3 mais cela est fait pour plusieurs autres raisons (cohérence , tolérance aux pannes) donc ce n'est pas nécessaire .. vous pouvez écrire à S3 assez rapidement en utilisant ce que j'ai suggéré.

14
Tal Joffe

Le committer direct a été tiré de spark car il n'était pas résistant aux échecs. Je déconseille fortement de l'utiliser.

Il y a du travail en cours dans Hadoop, s3guard, pour ajouter des committers 0-renommer, qui seront O(1) et tolérants aux pannes; gardez un œil sur HADOOP-13786 .

Ignorant "le committer Magic" pour l'instant, le committer de mise en scène basé sur Netflix sera expédié en premier (hadoop 2.9? 3.0?)

  1. Cela écrit le travail sur le FS local, dans la validation de tâche
  2. émet des opérations de vente multiparties non validées pour écrire les données, mais pas les matérialiser.
  3. enregistre les informations nécessaires pour valider le PUT sur HDFS, en utilisant le committer de sortie de fichier "algorithme 1" d'origine
  4. Implémente une validation de travail qui utilise la validation de sortie de fichier de HDFS pour décider quels PUT terminer et lesquels annuler.

Résultat: la validation de la tâche prend des données/bande passante secondes, mais la validation du travail ne prend pas plus de temps que de faire 1-4 GET sur le dossier de destination et un POST pour chaque fichier en attente, ce dernier étant parallélisé .

Vous pouvez choisir le committer sur lequel ce travail est basé, de netflix , et probablement l'utiliser dans spark aujourd'hui. Définissez l'algorithme de validation de fichier = 1 (devrait être la valeur par défaut) ou il n'écrira pas réellement les données.

6
Steve Loughran

J'ai eu un cas d'utilisation similaire où j'ai utilisé spark pour écrire dans s3 et j'ai eu un problème de performance. La raison principale était spark créait beaucoup de fichiers pièce de zéro octet et remplaçait les fichiers temporaires au nom de fichier réel ralentissaient le processus d'écriture.

  1. Écriture de la sortie de spark sur HDFS et utilisé Hive pour écrire dans s3. Les performances étaient bien meilleures car Hive créait moins de fichiers de pièces. Le problème que j'avais était (également eu le même problème lors de l'utilisation de spark)) , l'action de suppression sur la stratégie n'a pas été fournie dans prod env pour des raisons de sécurité. Le compartiment S3 a été kms chiffré dans mon cas.

  2. Ecrire spark sortie vers HDFS et fichiers hdfs copiés vers la copie aws s3 locale et utilisée pour pousser les données vers s3. A eu le deuxième meilleur résultat avec cette approche. Créé un ticket avec Amazon et ils ont suggéré d'aller avec cela une.

  3. Utilisez s3 dist cp pour copier des fichiers de HDFS vers S3. Cela fonctionnait sans problème, mais pas performant

5
Vikrame

Que voyez-vous dans spark output? Si vous voyez beaucoup d'opérations de renommage, lisez this

1
Niros

Nous avons vécu la même chose sur Azure en utilisant Spark sur WASB. Nous avons finalement décidé de ne pas utiliser le stockage distribué directement avec spark. Nous avons fait spark.write dans une véritable destination hdfs: // et développé une outil qui fait: hadoop copyFromLocal hdfs: // wasb: // Le HDFS est alors notre tampon temporaire avant l'archivage sur WASB (ou S3).

0
Julien Laurenceau

Quelle est la taille du ou des fichiers que vous écrivez également? Avoir un noyau écrit dans un fichier très volumineux sera beaucoup plus lent que de diviser le fichier et que plusieurs travailleurs écrivent des fichiers plus petits.

0
Ted