Deadlock quando vengono programmati contemporaneamente molti processi spark


17

Utilizzo di spark 2.4.4 in esecuzione in modalità cluster YARN con lo scheduler spark FIFO.

Sto inviando più operazioni di spark dataframe (cioè scrivendo dati su S3) usando un esecutore di pool di thread con un numero variabile di thread. Funziona bene se ho ~ 10 thread, ma se uso centinaia di thread, sembra che ci sia un deadlock, senza lavori pianificati secondo l'interfaccia utente di Spark.

Quali fattori controllano quanti lavori possono essere programmati contemporaneamente? Risorse del driver (ad es. Memoria / core)? Alcune altre impostazioni di configurazione della scintilla?

MODIFICARE:

Ecco una breve sinossi del mio codice

ExecutorService pool = Executors.newFixedThreadPool(nThreads);
ExecutorCompletionService<Void> ecs = new ExecutorCompletionService<>(pool);

Dataset<Row> aHugeDf = spark.read.json(hundredsOfPaths);

List<Future<Void>> futures = listOfSeveralHundredThings
  .stream()
  .map(aThing -> ecs.submit(() -> {
    df
      .filter(col("some_column").equalTo(aThing))
      .write()
      .format("org.apache.hudi")
      .options(writeOptions)
      .save(outputPathFor(aThing));
    return null;
  }))
  .collect(Collectors.toList());

IntStream.range(0, futures.size()).forEach(i -> ecs.poll(30, TimeUnit.MINUTES));
exec.shutdownNow();

Ad un certo punto, nThreadsall'aumentare, Spark non sembra più programmare alcun lavoro come evidenziato da:

  • ecs.poll(...) timeout alla fine
  • La scheda Lavori dell'interfaccia utente Spark non mostra lavori attivi
  • La scheda degli esecutori Spark dell'interfaccia utente non mostra attività attive per nessun esecutore
  • La scheda SQL dell'interfaccia utente Spark che mostra le nThreadsquery in esecuzione senza ID processo in esecuzione

Il mio ambiente di esecuzione è

  • AWS EMR 5.28.1
  • Spark 2.4.4
  • Nodo principale = m5.4xlarge
  • Nodi core = 3x rd5.24xlarge
  • spark.driver.cores=24
  • spark.driver.memory=32g
  • spark.executor.memory=21g
  • spark.scheduler.mode=FIFO


C'è una sezione specifica che ne discute? Ho letto più volte questi documenti negli ultimi giorni e non ho trovato la risposta che sto cercando.
Scott,

2
Potete per favore mostrare il codice che utilizzate per inviare i lavori Spark tramite l'esecuzione del pool di thread? Sembra che il deadlock si stia verificando prima che venga inviato il processo Spark.
Salim

1
Puoi pubblicare il tuo codice? Fornisci i dettagli sul tuo ambiente: CPU, RAM; anche come stai creando i thread: contemporaneamente o in piccoli gruppi di 10?
Saheed

Spiacenti, come intendi che i lavori non sono programmati? Non vengono visualizzati sull'interfaccia utente di Spark o vengono visualizzati nell'elenco dei lavori, ma le attività non vengono eseguite? In entrambi i casi, se si sospetta un deadlock, eseguire jstack -lper ottenere un dump del thread con informazioni di blocco.
Daniel Darabos,

Risposte:


0

Se possibile, scrivere l'output dei lavori su AWS Elastic MapReduce hdfs (per sfruttare le ridenominazioni quasi istantanee e migliorare il file IO degli hdf locali) e aggiungere un passaggio dstcp per spostare i file su S3, per salvare tutti i problemi di gestione del interiora di un archivio oggetti che cerca di essere un filesystem. Anche scrivere su hdf locali ti permetterà di abilitare la speculazione per controllare le attività in fuga senza cadere nelle trappole deadlock associate a DirectOutputCommiter.

Se è necessario utilizzare S3 come directory di output assicurarsi che siano impostate le seguenti configurazioni Spark

spark.hadoop.mapreduce.fileoutputcommitter.algorithm.version 2
spark.speculation false

Nota: DirectParquetOutputCommitter viene rimosso da Spark 2.0 a causa della possibilità di perdita di dati. Sfortunatamente, fino a quando non avremo migliorato la coerenza di S3a, dovremo lavorare con le soluzioni alternative. Le cose stanno migliorando con Hadoop 2.8

Evitare i nomi chiave in ordine lessicografico. Si potrebbe usare il prefisso hashing / prefissi casuali o la data-ora inversa per spostarsi. Il trucco è quello di nominare le chiavi gerarchicamente, mettendo le cose più comuni da filtrare sul lato sinistro della chiave. E non avere mai sottolineature nei nomi bucket a causa di problemi DNS.

Abilitazione fs.s3a.fast.upload uploadin parallelo di parti di un singolo file su Amazon S3

Fai riferimento a questi articoli per maggiori dettagli-

Impostazione di spark.speculation in Spark 2.1.0 durante la scrittura su s3

https://medium.com/@subhojit20_27731/apache-spark-and-amazon-s3-gotchas-and-best-practices-a767242f3d98



0

IMO probabilmente stai affrontando questo problema in modo sbagliato. A meno che non sia possibile garantire che il numero di attività per lavoro sia molto basso, è probabile che non si ottengano molti miglioramenti delle prestazioni parallelizzando centinaia di lavori contemporaneamente. Il cluster può supportare solo 300 attività alla volta, supponendo che si stia utilizzando il parallelismo predefinito di 200 ovvero solo 1,5 lavori. Suggerirei di riscrivere il codice per limitare il numero massimo di query simultanee a 10. Sospetto fortemente che tu abbia 300 query con una sola attività di diverse centinaia effettivamente in esecuzione. La maggior parte del sistema di elaborazione dati OLTP ha intenzionalmente un livello piuttosto basso di query simultanee rispetto ai sistemi RDS più tradizionali per questo motivo.

anche

  1. Apache Hudi ha un parallelismo predefinito di diverse centinaia di FYI.
  2. Perché non partizionare solo in base alla colonna del filtro?
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.