多くのスパークジョブが同時にスケジュールされる場合のデッドロック


17

YARNクラスターモードで実行されているSpark 2.4.4をSpark FIFOスケジューラーと共に使用する。

可変数のスレッドを持つスレッドプールエグゼキューターを使用して、複数のsparkデータフレーム操作(つまり、S3へのデータの書き込み)を送信しています。これは、スレッド数が10以下の場合は問題なく機能しますが、数百のスレッドを使用すると、デッドロックが発生し、Spark UIに従ってジョブがスケジュールされないように見えます。

同時にスケジュールできるジョブの数を制御する要因は何ですか?ドライバーリソース(メモリ/コアなど)?他のスパーク構成設定?

編集:

これが私のコードの簡単な概要です

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();

ある時点でnThreads、sparkが増加するにつれて、次のことからもわかるように、sparkがジョブをスケジュールしなくなったように見えます。

  • ecs.poll(...) 最終的にタイムアウトする
  • アクティブなジョブが表示されていないSpark UIのジョブタブ
  • Spark UIのexecutorタブには、executorのアクティブなタスクが表示されていません
  • nThreads実行中のジョブIDのない実行中のクエリを示すSpark UI SQLタブ

私の実行環境は

  • AWS EMR 5.28.1
  • Spark 2.4.4
  • マスターノード= m5.4xlarge
  • コアノード= 3x rd5.24xlarge
  • spark.driver.cores=24
  • spark.driver.memory=32g
  • spark.executor.memory=21g
  • spark.scheduler.mode=FIFO


これを説明する特定のセクションはありますか?私はこれらのドキュメントを過去数日間何度も読みましたが、探している答えが見つかりませんでした。
スコット

2
スレッドプールエグゼキューターを介してSparkジョブを送信するために使用するコードを示していただけますか?Sparkジョブが送信される前にデッドロックが発生しているようです。
サリム

1
コードを投稿できますか?環境の詳細を入力してください:CPU、RAM。また、どのようにスレッドを作成していますか?同時または10の小さなグループで?
サヒード

申し訳ありませんが、ジョブがスケジュールされていません。Spark UIに表示されないか、ジョブのリストに表示されますが、タスクは実行されませんか?どちらの方法でも、デッドロックが疑われる場合は、実行jstack -lしてロック情報を含むスレッドダンプを取得してください。
ダニエルダラボス

回答:


0

可能であれば、ジョブの出力をAWS Elastic MapReduce hdfsに書き込み(ほぼ瞬時の名前変更とローカルhdfsのより優れたファイルIOを活用するため)、ファイルをS3に移動するdstcpステップを追加して、ファイルシステムにしようとしているオブジェクトストアの内部。また、ローカルのhdfsに書き込むと、投機を有効にして、DirectOutputCommiterに関連付けられたデッドロックトラップに陥ることなく、暴走タスクを制御できます。

S3を出力ディレクトリとして使用する必要がある場合は、次のSpark構成が設定されていることを確認してください

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

注:データ損失の可能性があるため、DirectParquetOutputCommitterはSpark 2.0から削除されました。残念ながら、S3aからの整合性が改善されるまで、回避策を使用する必要があります。Hadoop 2.8で改善が進んでいます

キーネームを辞書式順序で使用しないでください。ハッシュ化/ランダムプレフィックスを使用するか、日付と時刻を逆にして回避することができます。トリックは、キーに階層的に名前を付け、フィルターの最も一般的なものをキーの左側に配置することです。DNSの問題のため、バケット名にアンダースコアを付けないでください。

fs.s3a.fast.upload upload単一のファイルの一部をAmazon S3に並行して有効にする

詳細については、これらの記事を参照してください

s3への書き込み中にSpark 2.1.0でspark.speculationを設定する

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



0

IMOあなたはおそらくこの問題に間違って取り組んでいます。ジョブあたりのタスク数が非常に少ないことが保証できない限り、一度に数百のジョブを並列化しても、パフォーマンスはそれほど向上しません。デフォルトの並列処理200、つまり1.5ジョブのみを使用している場合、クラスターは一度に300タスクのみをサポートできます。同時クエリの最大数を10に制限するようにコードを書き直すことをお勧めします。実際に実行されている数百の単一のタスクのみで300のクエリがあると思います。この理由により、ほとんどのOLTPデータ処理システムには、従来のRDSシステムと比較して、意図的にかなり低いレベルの同時クエリがあります。

また

  1. Apache Hudiには、デフォルトで数百の並列処理があります。
  2. フィルター列に基づいてパーティションを作成しませんか?
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.