このトピックでは、Sparkジョブ関連の問題のトラブルシューティング方法について説明します。
メモリ関連の問題
「Container killed by YARN for exceeding memory limits」というエラーが発生します。
- 原因:アプリケーションの送信時に要求されるメモリ量が少なすぎます。 Java Virtual Machine(JVM)は、起動時に割り当てられた量よりも多くのメモリを占有します。 その結果、ジョブはYARN NodeManagerによって異常終了します。 特に、Sparkジョブは大量のオフヒープメモリを消費する可能性があり、異常終了する可能性が高くなります。
- 解決策:EMRコンソールのSparkサービスページの [構成] タブで、spark.driver.memoryOverhead または spark.executor.memoryOverhead パラメーターの値を増やします。
オブジェクトストレージサービス(OSS)オブジェクトとのデータの読み取りまたは書き込みを行うSparkジョブを実行すると、「Container killed by YARN for exceeding memory limits」というエラーが発生します。
- 原因:OSSとのデータの読み取りまたは書き込み時に必要なメモリ量が上限を超えています。
- 解決策:Spark executorのメモリを増やします。 Spark executorのメモリを増やすことができない場合は、EMRコンソールのHadoop-Commonサービスページの [core-site.xml] タブで、次のパラメーターを変更できます。
- fs.oss.read.readahead.buffer.count: 0
- fs.oss.read.buffer.size: 16384
- fs.oss.write.buffer.size: 16384
- fs.oss.memory.buffer.size.max.mb: 512
「Error: Java heap space」というエラーが発生します。
- 原因:Sparkジョブは大量のデータを処理する必要がありますが、JVMのメモリが不足しています。 その結果、メモリ不足(OOM)エラーが返されます。
- 解決策:EMRコンソールのSparkサービスページの [構成] タブで、ビジネス要件に基づいて spark.executor.memory または spark.driver.memory パラメーターの値を増やします。
Snappyファイルを読み取るためにSparkジョブを実行すると、OOMエラーが発生します。
EMRコンソールのSparkサービスページの [spark-defaults.conf] タブで、spark.hadoop.io.compression.codec.snappy.native パラメーターを追加し、値をtrueに設定します。
Sparkドライバーのメモリ不足が原因でOOMエラーが発生します。
次のいずれかの解決策を使用して、問題をトラブルシューティングできます。
- EMRコンソールのSparkサービスページの [構成] タブで、spark.driver.memory パラメーターの値を増やします。
- collect操作などの操作がSparkドライバーにデータを取得するために実行されているかどうかを確認します。 収集されるデータ量が大きい場合は、foreachPartitionsを使用してexecutorで操作を実行し、collect操作に関連するコードを削除することをお勧めします。
- spark.sql.autoBroadcastJoinThreshold パラメーターを -1 に設定します。
Spark executorのメモリ不足が原因でOOMエラーが発生します。
次のいずれかの解決策を使用して、問題をトラブルシューティングできます。
- EMRコンソールのSparkサービスページの [構成] タブで、spark.executor.memory パラメーターの値を増やします。
- spark.executor.cores パラメーターの値を減らします。
- spark.default.parallelism および spark.sql.shuffle.partitions パラメーターの値を増やします。
ファイル形式関連の問題
Sparkを使用してインポートされたParquetテーブルを読み取るためにHiveまたはImpalaジョブを実行すると、エラーが発生します。
- エラーメッセージ:
Failed with exception java.io.IOException:org.apache.parquet.io.ParquetDecodingException: Can not read value at 0 in block -1 in file xxx。 - 原因:DECIMALデータ型は、HiveとSparkで使用される異なるParquet規則で異なる表現をしています。 Sparkを使用してインポートされたParquetデータは、HiveまたはImpalaを使用して正しく読み取ることができません。
- 解決策:EMRコンソールのSparkサービスページの spark.sql.parquet.writeLegacyFormat[spark-defaults.conf] タブで、 パラメーターを追加し、値をtrueに設定します。 Sparkを使用してParquetデータを再度インポートします。 その後、HiveまたはImpalaジョブを実行してParquetデータを読み取ることができます。
シャッフル関連の問題
「java.lang.IllegalArgumentException: Size exceeds Integer.MAX_VALUE」というエラーが発生します。
- 原因:データシャッフル中に、パーティションの数が非常に少なくなっています。 その結果、ブロックサイズがInteger.MAX_VALUEパラメーターの値を超えています。
- 解決策:spark.default.parallelism および spark.sql.shuffle.partitions パラメーターを大きな値に設定することにより、パーティションの数を増やします。 データシャッフルを実行する前に、repartition操作を実行することもできます。
外部データソース関連の問題
「java.sql.SQLException: No suitable driver found for jdbc:mysql:xxx」というエラーが発生します。
以前のバージョンのmysql-connector-javaが使用されています。 5.1.48以降のバージョンに更新してください。
SparkがApsaraDB RDSに接続されているときに、「Invalid authorization specification, message from server: ip not in whitelist」というエラーが発生します。
ApsaraDB RDSのホワイトリスト設定を確認し、すべてのEMRクラスターノードの内部IPアドレスをApsaraDB RDSのホワイトリストに追加します。
その他の問題
Spark UIにジョブが割り当てられていないか、Spark UIに表示されているすべてのジョブの実行が完了しているが、Sparkタスクが長時間終了しない。
SparkのWeb UIに移動します。 Spark executorプロセスを見つけ、ドライバーのスレッドダンプを分析します。 多数のORC関連スレッドが存在する場合は、--conf spark.hadoop.hive.exec.orc.split.strategy パラメーターをBIに設定し、Sparkタスクを再起動します。 Spark 2.Xの場合は、spark.sql.adaptive.enabled パラメーターの値がtrueであるかどうかを確認する必要があります。 値がtrueの場合は、値をfalseに変更します。
Sparkタスクが長時間終了せず、SparkのWeb UIにアクセスできない。
- 原因:Sparkドライバーのメモリが不足しており、フルガベージコレクション(GC)が発生しています。
- 解決策:spark.driver.memory パラメーターの値を増やします。
SparkがHiveデータを読み取るコードを実行すると、「NoSuchDatabaseException: Database 'xxx' not found」というエラーが発生します。
- Sparkセッションを初期化するときに、
.enableHiveSupport()メソッドが呼び出されているかどうかを確認します。 .enableHiveSupport() メソッドが呼び出されていない場合は、手動でメソッドを呼び出します。 - コードで
new SparkContext()メソッドが呼び出されているかどうかを確認します。 new SparkContext() メソッドが呼び出されている場合は、メソッドに関連するコードを削除し、SparkセッションからSparkコンテキストを取得します。
Sparkジョブで「java.lang.ClassNotFoundException」というエラーが発生します。
クラス情報に基づいて特定のJARパッケージを見つけ、次のいずれかの方法でJARパッケージを処理します。
- 方法 1:Sparkジョブを送信するときに、
--jarsコマンドを使用してJARパッケージを送信します。 - 方法 2:spark.driver.extraclasspath および spark.executor.extraclasspath パラメーターでJARパッケージのパスを指定します。 この方法では、JARパッケージがEMRクラスターの各ノードに存在する必要があります。