記事ディレクトリ
1.リソースの調整
1.1Sparkクラスターを構築するときにCPUとメモリを構成する
Sparkインストールパッケージの設定でspark-env.shを構成します
構成 | 説明 | デフォルト |
---|---|---|
SPARK_WORKER_CORES | ジョブに使用できるCPUコアの数 | 利用可能なすべてのCPUコア |
SPARK_WORKER_INSTANCES | 各マシンで実行されているワーカーの数 | 1 |
SPARK_WORKER_CORES×SPARK_WORKER_INSTANCES | マシンあたりの合計コア | |
SPARK_WORKER_MEMORY | 操作可能なメモリ容量 | 1G |
SPARK_WORKER_INSTANCES×SPARK_WORKER_MEMORY | 各ノードで使用されるメモリの最大量 | |
SPARK_DAEMON_MEMORY | Sparkマスターデーモンとワーカーデーモンに割り当てられたメモリスペース | 512M |
1.2アプリケーションを送信するときに、アプリケーションにより多くのリソースを割り当てます
コマンドオプションの送信:
每个executor使用的core数,spark on yarn 默认为1,standalone默认为worker上所有可用的core。
--executor-cores
每个executor内存大小(例如:2G),默认1G
--executor-memory
executor使用的总核数,仅限于SparkStandalone、Spark on Mesos模式
--total-executor-cores
2.パラレルチューニング
原則:コアは通常2〜3個のタスクを割り当て、各タスクは通常1Gデータを処理します。
並列処理を改善する方法:
-
読み取ったデータがHDFSにある場合は、ブロックサイズを小さくします。
-
sc.textFile(path,numPartitions)
-
sc.parallelize(list, numPartitions)
一般的にテストに使用されます -
coalesce
、repartition
RDDパーティションの数を増やすことができます。 -
構成情報の変更:
spark.default.parallelism:4
:デフォルトのエグゼキュータコアの総数を設定しないでくださいspark.sql.shuffle.partitions 200
-
カスタムパーティショナー
3.コードチューニング
3.1重複するRDDの作成を避ける
val rdd1 = sc.textFile("xxx")
val rdd2 = sc.textFile("xxx")
実行効率に違いはありませんが、コードが乱雑です。
-
他のジョブでは、繰り返し使用されるRDDに永続性演算子を使用する必要があります
-
キャッシュ:
MEMORY_ONLY
-
持続する:
MEMORY_ONLY
MEMORY_ONLY_SER
MEMORY_AND_DISK_SER
通常、_2の永続性レベルは選択しないでください
-
チェックポイント
RDDの計算時間が比較的長い場合、または計算がより複雑な場合は、通常、このRDDの計算結果をHDFSに保存して、データの安全性を高めます。
RDDの依存関係が非常に長い場合は、チェックポイントも使用されます。これにより、依存関係が遮断され、フォールトトレランスの効率が向上します。
-
3.2ブロードキャスト変数を使用してみてください
開発プロセス中に、演算子関数で外部変数を使用する必要があるシナリオが発生します(特に、100Mを超える大きなコレクションなどの大きな変数)。次に、Sparkのブロードキャスト変数(Broad
パフォーマンスを向上させるためのキャスト)関数。関数で外部変数が使用されている場合、デフォルトでは、Sparkは変数の複数のコピーを作成し、ネットワーク経由でタスクに転送します。この時点で、各タスクには変数コピーがあります。変数自体が比較的大きい場合(100M、さらには1Gなど)、ネットワーク伝送での多数の変数コピーのパフォーマンスオーバーヘッド、およびExecutorの各ステージでの過剰なメモリ使用により、GCが頻繁に発生し、パフォーマンスに大きな影響を与えます。使用する外部変数が比較的大きい場合は、Sparkのブロードキャスト機能を使用して変数をブロードキャストすることをお勧めします。ブロードキャスト後、変数は各エグゼキュータのメモリ内で爆発し、エグゼキュータ内のタスクの実行中に変数のコピーが1つだけ存在します。 Executorで変数のコピーを共有します。このようにして、可変コピーの数を大幅に減らすことができるため、ネットワーク送信のパフォーマンスオーバーヘッドが削減され、Eexcutorのメモリ使用量が削減され、GCの頻度が削減されます。
大きな変数の送信方法のブロードキャスト:Executorは最初は変数をブロードキャストしませんでしたが、タスク操作はブロードキャスト変数を使用する必要があり、ExecutorのBlockManagerを見つけます。BlockManagerは、DriverでBlockManagerMasterを見つけます。
ブロードキャスト変数を使用すると、クラスター内の変数のコピー数を大幅に減らすことができます。
ブロードキャスト変数を使用しない:変数のコピーの数は、タスクの数と同じです。
ブロードキャスト変数を使用する:変数のコピーの数は、Executorの数と同じです。
ブロードキャスト変数が占める最大メモリ:ExecutorMemory * 60%* 90%* 80%
3.3シャッフル演算子の使用は避けてください
ブロードキャスト変数を使用して、結合の使用シナリオをシミュレートします。1つのRDDは比較的大きく、1つのRDDは比較的小さくなります。
結合演算子=ブロードキャスト変数+フィルター、ブロードキャスト変数+マップ、ブロードキャスト変数+ flatMap
3.4マップ側の事前集計を使用したシャッフル操作
コンバイナのシャッフル演算子を使用してみてください。
コンバイナの概念:マップ側では、各マップタスクが計算された後にローカル集計が実行されます。
コンバイナーの利点:
- シャッフル書き込みによってディスクに書き込まれるデータの量を減らします。
- シャッフル読み取りによってプルされるデータの量を減らします。
- 削減側の集計の数を減らします。
コンバイナーのシャッフルオペレーターがあります:
reduceByKey
:この演算子には、マップ側にコンバイナーがあります。一部のシナリオでは、groupByKeyの代わりにreduceByKeyを使用できます。aggregateByKey
。combineByKey
。
3.5高性能演算子を使用してみてください
reduceByKey
代替を使用するgroupBkKey。
- の
mapPartition
代わりに使用map。
foreachPartition
代替を使用するforeach。
filter
coalesce
パーティションの数を減らすために使用した後。repartitionAndSortWithinPartitions
代替repartition
とsort
操作の使用。
3.6Kryoを使用してシリアル化のパフォーマンスを最適化する
3.6.1 Sparkでは、シリアル化は主に次の3つの場所で行われます。
- 外部変数が演算子関数で使用される場合、変数はネットワーク送信のためにシリアル化されます。
- カスタムタイプをRDDの汎用タイプとして使用する場合(たとえば
JavaRDD<User>
、ユーザーはカスタムタイプです)、すべてのカスタムタイプオブジェクトがシリアル化されます。したがって、この場合、カスタムクラスもSerializable
インターフェイスを実装する必要があります。 - シリアル化可能な永続化戦略(MEMORY_ONLY_SERなど)を使用する場合、SparkはRDD内のすべてのパーティションを大きなバイト配列にシリアル化します。
3.6.2Kryoシリアライザーの概要
Sparkは、Kryoシリアル化メカニズムの使用をサポートしています。Kryoのシリアル化メカニズムはデフォルトのJavaシリアル化メカニズムよりも高速であり、シリアル化されたデータは小さく、Javaシリアル化メカニズムの約1/10です。したがって、Kryoのシリアル化後、ネットワークを介して送信されるデータを減らすことができます。クラスタで消費されるメモリリソースが大幅に削減されます。
シリアル化が発生するこれらの3つの場所では、Kryoシリアル化ライブラリを使用して、シリアル化と逆シリアル化のパフォーマンスを最適化できます。SparkはデフォルトのJavaシリアル化メカニズムであり、ObjectOutputStream/ObjectInputStream API
シリアル化および逆シリアル化されます。ただし、SparkはKryoシリアル化ライブラリの使用もサポートしています。Kryoシリアル化ライブラリのパフォーマンスは、Javaシリアル化ライブラリのパフォーマンスよりもはるかに高くなっています。公式の紹介によると、Kryoのシリアル化メカニズムはJavaのシリアル化メカニズムの約10倍です。SparkがデフォルトでKryoシリアル化ライブラリを使用しない理由は、Kryoでは、シリアル化が必要なカスタムタイプを登録する方がよいと要求しているため、この方法は開発者にとってより面倒です。
3.6.3SparkでのKryoの使用
SparkConf conf = new SparkConf();
conf.setMaster("local");
conf .set("spark.serializer","org.apache.spark.serializer.KryoSerializer");
conf.registerKryoClasses(new Class[]{
CameraAggInfo.class});
3.7データ構造の最適化
javaのメモリ消費には次の3つのタイプがあります。
- オブジェクト。各Javaオブジェクトには、オブジェクトヘッダーや参照などの追加情報があるため、より多くのメモリスペースを使用します。
- 文字列。各文字列には、文字配列の長さなどの追加情報が含まれています。
- 一部の内部クラスは通常、Map.Entryなどのコレクション要素をカプセル化するために使用されるため、HashMap、Listなどのコレクションタイプ。
したがって、Sparkは、Sparkコーディング、特に演算子関数のコードで、Jinlbuyが上記の3つのデータ構造を使用することを公式に推奨しています。オブジェクトの代わりに文字列を使用し、文字列の代わりにプリミティブデータタイプ(Int、Longなど)を使用し、コレクションタイプの代わりに配列を使用してメモリ使用量を可能な限り減らし、GCの頻度を減らしてパフォーマンスを向上させます。
3.8高性能ライブラリfastutilを使用する
fastutilは、Java標準コレクションフレームワーク(Map、List、Set)を拡張し、特別なタイプのmap、set、list、およびqueueを提供するクラスライブラリです。fastutilは、メモリフットプリントを小さくし、アクセス速度を高速化できます。通常使用するJDKネイティブコレクションの代わりに、fastutilが提供するコレクションクラスを使用します。利点は、fastutilコレクションクラスがメモリ使用量を削減できることです。コレクションをトラバースし、インデックス(またはキー)に従って要素の値を取得し、要素の値を設定します。の場合、より速いアクセス速度を提供します。fastutilの各コレクションタイプは、対応するJavaの標準インターフェイス(たとえば、JavaのMapインターフェイスを実装するfastutilのマップ)を実装しているため、既存のシステムの任意のコードに直接配置できます。
fastutilの最新バージョンには、Java7以降が必要です。