记录:エラーYarnScheduler:XXXでエグゼキュータ2を失いました:メモリ制限を超えたためにYARNによってコンテナが強制終了されました

問題の説明

最近、pysparkが90Gを超えるデータを処理しているときに、この問題が発生しました。

まず、次のエラーまたは警告が表示される場合があります。

Lost executor 2 on bjxg-bd-slave65: Container killed by YARN for exceeding memory limits. 
 60.1 GB of 55 GB physical memory used. Consider boosting spark.yarn.executor.memoryOverhead 
 or disabling yarn.nodemanager.vmem-check-enabled because of YARN-4714

ここに画像の説明を挿入
または、アクション演算子を実行するときにこの種の問題が発生します。

ここに画像の説明を挿入

Web UIには、多くのユーザーがいることがわかります。失敗した

ここに画像の説明を挿入

解決

1.データが歪んでいないことを確認します

groupbyなどのグループ化集計操作を使用すると、データ量が多いとデータスキューが発生し、特定のタスクで特に大量のデータが発生し、割り当てられたメモリを超えるメモリが強制終了される場合があります。両端で集約する方法など、最適化できる子のみです。詳細については、以下を参照してください。

https://blog.csdn.net/qq_42363032/article/details/119824492

2.キャッシュを使用して、オペレーターを調整する

  • 次に、レイジーオペレーターが繰り返し実行されないようにします。アクションオペレーターの前に、キャッシュまたは永続化を使用してキャッシュします。もちろん、ストレージレベルを設定することもできます。詳細については、Baiduを使用できます。
  • スパークオペレーターのチューニングについてもたくさんあります。私はこのエラーを解決するために使用したものだけを言います。
    • 1.大きな変数のブロードキャストをブロードキャストします。使用後は手動でGCを非永続化することを忘れないでください
    • 2.ドライバー側にプルされるカウント、収集、およびその他のアクションオペレーターの使用を最小限に抑えます。それらの前にキャッシュを追加し、使用後に主張することができます。なぜ前にキャッシュを追加するのですか?スパーク遅延計算のため。
    • 3.大きなテーブルと小さなテーブルを結合するシャッフル操作は避けてください。避けられない場合は、ブロードキャストを使用できます。これもBaiduの多くです。
    • 4.処理する場合、処理中のメモリ使用量と通信時間を削減するために、選択またはフィルタを介したシャッフルによって削減できるデータを事前に削減する必要があります。
    • 5.処理しているデータにnullがないことを確認します。試してみました。nullがある場合は、nullがない場合よりも明らかに高速です。空の文字列を入力しても、nullよりも優れています。

3.リソースの調整

Baiduで見つけることができます。多くの人が、この種のエラーに対してエグゼキュータメモリとエグゼキュータメモリオーバーヘッドを追加すると言います。これを追加するのは正しいですが、処理プロセス全体を確認する必要があります。オペレータは、どこにあるかを考えることができません。最適化してからリソースを追加します。これが正しいチューニングロジックです。最初に私のリソースを共有します:

ss = SparkSession(sc).builder \
    .config('spark.sql.shuffle.partitions', 3000) \
    .config('spark.driver.memoryOverhead', '30g') \
    .config('spark.driver.maxResultSize', '30g') \
    .config('spark.executor.memoryOverhead', '40g') \
    .config('spark.shuffle.io.maxRetries', 10) \
    .config('spark.shuffle.io.retryWait', 10) \
    .config('spark.default.parallelism', 30) \
    .config('spark.kryoserializer.buffer.max', 5120) \
    .config('spark.dynamicAllocation.enabled', 'true') \
    .config("spark.sql.execution.arrow.enabled", "true")\
    .config("spark.memory.fraction", 0.2)\
    .config('spark.sql.caseSensitive', 'true') \
    .getOrCreate()
PYSPARK_PYTHON=/data/anaconda3/bin/python3 \
  /opt/spark/bin/spark-submit \
      --master yarn \
      --deploy-mode client \
      --driver-memory 30g \
      --driver-cores 4 \
      --executor-memory 50g \
      --num-executors 6 \
      --executor-cores 5 \
  • driver-memorydriver-cores:文字通り、データの量と処理の複雑さに応じて設定される、ドライバーのメモリとコアの数を意味します
  • executor-memory、、 :それぞれnum-executorsexecutor-coresエグゼキュータのメモリ、量、およびコアの数。これらは、処理されるデータの量と複雑さに応じて設定されます。これら2つは、50 * 6のメモリ、およびコアの数6を与えることに相当します。 * 5は私のrddに相当します。並列処理の最高度は30です。executor-coresは6を超えてはならず、最高はnum-executorsであるという記事を見たのを覚えています。
  • spark.sql.shuffle.partitions:spark sqlの並列処理は、ビッグデータにも役立ちます。データの偏りをわずかに防ぐことができますが、小さいデータの並列処理は高すぎないようにする必要があります。そうしないと、実行速度が遅くなります。デフォルトは200です。
  • spark.driver.memoryOverhead:ドライバのオフヒープメモリ
  • spark.driver.maxResultSize:これは、すべてのパーティションのシリアル化結果のサイズの合計です。エグゼキュータメモリより大きくすることはできません。範囲内で増やすと、メモリ不足を防ぐことができます。
  • spark.executor.memoryOverhead:エグゼキュータのオフヒープメモリ、エグゼキュータに必要な追加のメモリオーバーヘッドであると理解しています
  • spark.default.parallelism:rddの並列度、エグゼキュータ数とコア数の乗数です。たとえば、私にとっては5*10です。
  • spark.memory.fraction:この値は調整する必要があります。デフォルトは0.6です。これは、スペースの40%がデータ構造やメタデータなどのために予約されていることを意味します。0.2に調整すると、80%のスペースを保持できることを意味します。あなたのデータ。キャッシュする場合、最初にディスクに配置し、次にメモリに配置することができます。これは、キャッシュに使用されるメモリを削減することと同じです。



それがあなたを助けるならば、好きで、サポートしてください

おすすめ

転載: blog.csdn.net/qq_42363032/article/details/123730750