web-dev-qa-db-fra.com

Comment éviter que Spark l'exécuteur ne se perde et que le conteneur de fils le tue à cause de la limite de mémoire?

J'ai le code suivant qui déclenche hiveContext.sql() la plupart du temps. Ma tâche est que je veux créer quelques tables et insérer des valeurs après le traitement de toutes les partitions de table Hive.

J'ai donc d'abord tiré show partitions et en utilisant sa sortie dans une boucle for, j'appelle quelques méthodes qui créent la table (si elle n'existe pas) et les insère en utilisant hiveContext.sql.

Maintenant, nous ne pouvons pas exécuter hiveContext dans un exécuteur, je dois donc l'exécuter dans une boucle for dans un programme de pilote, et nous devons l'exécuter en série un par un. Lorsque je soumets ce travail Spark dans le cluster YARN, presque tout le temps mon exécuteur est perdu en raison d'une exception de lecture aléatoire introuvable.

Maintenant, cela se produit parce que YARN tue mon exécuteur à cause d'une surcharge de mémoire. Je ne comprends pas pourquoi, car j'ai un très petit ensemble de données pour chaque partition Hive, mais cela provoque quand même YARN à tuer mon exécuteur.

Le code suivant fera-t-il tout en parallèle et tentera-t-il de gérer toutes les données de partition Hive en mémoire en même temps?

public static void main(String[] args) throws IOException {   
    SparkConf conf = new SparkConf(); 
    SparkContext sc = new SparkContext(conf); 
    HiveContext hc = new HiveContext(sc); 

    DataFrame partitionFrame = hiveContext.sql(" show partitions dbdata partition(date="2015-08-05")"); 
  
    Row[] rowArr = partitionFrame.collect(); 
    for(Row row : rowArr) { 
        String[] splitArr = row.getString(0).split("/"); 
        String server = splitArr[0].split("=")[1]; 
        String date =  splitArr[1].split("=")[1]; 
        String csvPath = "hdfs:///user/db/ext/"+server+".csv"; 
        if(fs.exists(new Path(csvPath))) { 
            hiveContext.sql("ADD FILE " + csvPath); 
        } 
        createInsertIntoTableABC(hc,entity, date); 
        createInsertIntoTableDEF(hc,entity, date); 
        createInsertIntoTableGHI(hc,entity,date); 
        createInsertIntoTableJKL(hc,entity, date); 
        createInsertIntoTableMNO(hc,entity,date); 
   } 
}
16
Umesh K

En règle générale, vous devez toujours creuser dans les journaux pour obtenir la véritable exception (au moins dans Spark 1.3.1).

tl; dr
config sûre pour Spark sous Yarn
spark.shuffle.memoryFraction=0.5 - cela permettrait d'utiliser de manière aléatoire plus de mémoire allouée
spark.yarn.executor.memoryOverhead=1024 - ceci est défini en Mo. Yarn tue les exécuteurs lorsque son utilisation de la mémoire est plus grande que (exécuteur-mémoire + executor.memoryOverhead)

n peu plus d'informations

En lisant votre question, vous mentionnez que vous obtenez une exception non trouvée.

En cas de org.Apache.spark.shuffle.MetadataFetchFailedException: Missing an output location for shuffle vous devez augmenter spark.shuffle.memoryFraction, par exemple à 0,5

La raison la plus courante pour laquelle Yarn tuait mes exécuteurs était l'utilisation de la mémoire au-delà de ses attentes. Pour éviter que vous augmentiez spark.yarn.executor.memoryOverhead, Je l'ai mis à 1024, même si mes exécuteurs testent seulement 2-3G de mémoire.

18
Barak1731475

C'est mon hypothèse: vous devez avoir des exécuteurs limités sur votre cluster et le travail peut être exécuté dans un environnement partagé.

Comme vous l'avez dit, la taille de votre fichier est petite, vous pouvez définir un plus petit nombre d'exécuteurs et augmenter les cœurs d'exécuteurs et définir la propriété memoryOverhead est important ici.

  1. Définir le nombre d'exécuteurs = 5
  2. Définir le nombre de cœurs exécuteurs = 4
  3. Définir la surcharge de mémoire = 2G
  4. partition aléatoire = 20 (pour utiliser le parallélisme maximum basé sur les exécuteurs et les cœurs)

En utilisant la propriété ci-dessus, je suis sûr que vous éviterez les problèmes de mémoire insuffisante de l'exécuteur sans compromettre les performances.

0
Ajay Ahuja