Sparkのパフォーマンスチューニングと障害処理(1)Sparkの定期的なパフォーマンスチューニング

1.最適なリソース割り当て

Sparkパフォーマンスチューニングの最初のステップは为任务分配更多的资源,在一定范围内,增加资源的分配与性能的提升是成正比的,实现了最优的资源配置后,在此基础上再考虑进行后面论述的性能调优策略。

リソースの割り当ては、スクリプトを使用してSparkタスクを送信するときに指定されます。標準のSparkタスク送信スクリプトは次のとおりです。

/usr/opt/modules/spark/bin/spark-submit \
--class com.atguigu.spark.Analysis \
--num-executors 80 \
--driver-memory 6g \
--executor-memory 6g \
--executor-cores 3 \
/usr/opt/modules/spark/jar/spark.jar \

割り当て可能なリソースを次の表に示します。
ここに画像の説明を挿入

規制原則尽量将任务分配的资源调节到可以使用的资源的最大限度。

特定のリソースの割り当てについては、Sparkの2つのクラスター操作モードについて個別に説明します。

1つ目はSpark Standalone 模式、タスクを送信する前に、運用および保守部門から利用可能なリソースを知っているか入手する必要あることです。送信スクリプトを作成するときは、利用可能なリソースに基づいてリソースを割り当てます。たとえば、クラスターには15台のマシン。各マシンには8Gメモリと2つのCPUコアがあり、15人のエグゼキューターが割り当てられ、各エグゼキューターには8Gメモリと2つのCPUコアが割り当てられます。

2つ目はSpark Yarn 模式、Yarnはリソースの割り当てとスケジューリングにリソースキューを使用するため、送信スクリプトを作成するときに、Sparkジョブが送信されるリソースキューに従ってリソースを割り当てることです。たとえば、リソースキューには400Gのメモリと100のCPUがあります。コア、次に50のエグゼキューターを指定すると、各エグゼキューターは8Gのメモリと2つのCPUコアを割り当てます。

表のリソースを調整した後、得られたパフォーマンスの向上を次の表に示します。
ここに画像の説明を挿入
補足:本番環境でのSpark submitのスクリプト構成

/usr/local/spark/bin/spark-submit \
--class com.atguigu.spark.dataetl \
--num-executors 80 \
--driver-memory 6g \
--executor-memory 6g \
--executor-cores 3 \
--master yarn-cluster \
--queue root.default \
--conf spark.yarn.executor.memoryOverhead=2048 \
--conf spark.core.connection.ack.wait.timeout =300 \
/usr/local/spark/spark.jar



参数配置参考值:
--num-executors:50~100
--driver-memory:1G~5G
--executor-memory:6G~10G
--executor-cores:3
--master:实际生产环境一定使用 yarn-cluster

2、RDDの最適化

2.1 RDD复用

RDDで演算子を実行するときは
ここに画像の説明を挿入
の図に示すように、同じ演算子と計算ロジックの下でRDDで繰り返し計算を行わないでください。上図のRDD計算アーキテクチャを変更して、の図に示す最適化結果を取得します。 :
ここに画像の説明を挿入

2.2 RDD 持久化

Sparkでは、同じRDDでオペレーター操作が複数回実行されると、RDDは前の親RDDで毎回再計算されます。この状況は回避する必要があります对同一个 RDD 的重复计算是对资源的极大浪费。したがって、複数の用途に使用する必要がありますRDDは永続化され、パブリックRDDのデータは永続化によってメモリ/ディスクにキャッシュされます。その後、パブリックRDDの計算は、メモリ/ディスクから直接RDDデータを取得します。

RDDの永続性について、説明する必要がある2つのポイントがあります。

まず、RDDの永続化が可能序列化です。メモリがRDDデータを完全に格納できない場合は、シリアル化を使用してデータ量を減らし、データをメモリに完全に格納することを検討できます。

次に、データの信頼性が非常に高く、メモリが十分である場合副本机制、RDDデータを保持するために使用できます。永続化のためにコピーメカニズムを有効にすると、永続化のデータユニットごとにコピーが保存され、他のノードに配置されるため、データのフォールトトレランスが実現します。データのコピーが失われたら、再計算する必要はありません。コピー。

2.3 RDDフィルター操作をできるだけ早く

初期RDDを取得したら、不要なデータをできるだけ早く除外することを検討してください。これにより、メモリ使用量が削減され、Sparkジョブの効率が向上します。

3、大きな変数をブロードキャストする

デフォルトでは、タスクのオペレーターで外部変数が使用されている場合、各タスクは変数のコピーを取得するため、メモリが大量に消費されます。一方では、RDDが引き続き永続化される場合、RDDデータはメモリに格納されず、ディスクにのみ書き込むことができます。ディスクIOはパフォーマンスを大幅に消費します。他方、タスクがオブジェクトを作成すると、ヒープが見つかる場合がありますメモリには、新しく作成されたオブジェクトを格納できません。これにより、GCが頻繁に発生し、ワーカースレッドが停止し、Sparkが一定期間作業を中断し、Sparkのパフォーマンスに深刻な影響を及ぼします。

現在のタスクが20個のエグゼキューターで構成され、500個のタスクが指定され、20Mの変数がすべてのタスクで共有されているとします。このとき、500個のタスクの500個のコピーが生成され、10Gのクラスターメモリを消費します。ブロードキャスト変数が使用されている場合、各エグゼキューターは、合計400Mのメモリを消費するコピーを保存し、メモリ消費量は5分の1に削減されます。

广播变量在每个 Executor 保存一个副本,此 Executor 的所有 task 共用此广播变量,这让变量产生的副本数量大大减少。

初期段階では、Driverにはブロードキャスト変数のコピーが1つしかありません。タスクが実行されているときに、ブロードキャスト変数のデータを使用する場合は、まずローカルエグゼキューターに対応するBlockManagerで変数を取得しようとします。如果本地没有,BlockManager 就会从 Driver 或者其他节点的 BlockManager上远程拉取变量的复本,并由本地的 BlockManager 进行管理;次に、このエグゼキューターのすべてのタスクがローカルBlockManagerから直接変数を取得します。

4、Kryoシリアル化

默认情况下,Spark 使用 Java 的序列化机制Javaのシリアル化メカニズムは使いやすく、追加の構成は必要ありません。オペレーターで使用される変数はSerializableインターフェースを実装できます。ただし、Javaシリアル化メカニズムは効率的ではなく、シリアル化速度が遅く、シリアル化されたデータが占有されますスペースはまだ大きいです。

Kryoシリアライゼーションメカニズムは、Javaシリアライゼーションメカニズムよりも約10倍高速です。SparkがデフォルトでシリアライゼーションライブラリとしてKryoを使用しないのは、すべてのオブジェクトのシリアライゼーションをサポートしていないためです。同時に、Kryo 需要用户在使用前注册需要序列化的类型十分ではありませんが、Spark 2.0.0以降です。このバージョンから、単純型、単純型配列、および文字列型のシャッフルRDDがデフォルトでKryoによってシリアル化されました。

Kryoシリアル化登録メソッドのサンプルコードは次のとおりです。

public class MyKryoRegistrator implements KryoRegistrator
{
    
    
	 @Override
	 public void registerClasses(Kryo kryo)
	 {
    
    
	 kryo.register(StartupReportLogs.class);
	 }
}

Kryoシリアル化を構成するためのサンプルコードは次のとおりです。

//创建 SparkConf 对象
val conf = new SparkConf().setMaster().setAppName()
//使用 Kryo 序列化库,如果要使用 Java 序列化库,需要把该行屏蔽掉
conf.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer");
//在 Kryo 序列化库中注册自定义的类集合,如果要使用 Java 序列化库,需要把该行屏蔽掉
conf.set("spark.kryo.registrator", "atguigu.com.MyKryoRegistrator"); 

5、ローカリゼーションの待機時間を調整します

Sparkジョブの実行中に、ドライバーは各ステージのタスクを割り当てます。根据 Spark的 task 分配算法,Spark 希望 task 能够运行在它要计算的数据所在的节点(数据本地化思想)、データのネットワーク送信を回避できるようにします。一般的に言って、これらのノードで使用可能なリソースが使い果たされている可能性があるため、タスクがデータを処理するノードに割り当てられていない可能性があります。このとき、Sparkは如果等待指定时间后仍然无法在指定节点运行,那么会自动降级,尝试将 task 分配到比较差的本地化级别所对应的节点上、タスクをノードから離れたノードに割り当てるなど、一定の時間、デフォルトは3秒待機します。より新しいデータノードを計算し、次にを計算し如果当前级别仍然不行,那么继续降级ます。

タスクによって処理されるデータが、タスクが配置されているノード上にない場合、データ送信が発生します。タスクは、データが配置されているノードのBlockManagerを介してデータを取得します。BlockManagerがデータがローカルでないことを検出すると、ネットワーク転送コンポーネントを介して、データが配置されているノードのBlockManagerからデータを取得します。

データのネットワーク送信の状況は見たくないものです大量的网络传输会严重影响性能。そのため、ローカライズされた待機時間を調整したいと考えています。待機時間中にターゲットノードがタスクの一部を完了した場合、現在のタスクは実行。Sparkジョブの全体的なパフォーマンスを向上させることができます。

Sparkのローカリゼーションレベルを次の表に示します
ここに画像の説明を挿入
。Sparkプロジェクトの開発フェーズでは、クライアントモードを使用してプログラムをテストできます。このとき、比較的完全なログ情報をローカルで確認でき、ログ情報には明確なタスクデータのローカリゼーションがありますレベル、それらのほとんどがPROCESS_LOCALである場合、調整する必要はありませんが、多くのレベルがNODE_LOCAL、AN​​Yであることがわかった場合は、ローカライズ待機時間を調整する必要があります。ローカライズ待機時間を延長して、ローカルタスクを確認してください。最適化のレベルが改善されているかどうか、およびSparkジョブの実行時間が短縮されているかどうかを確認します。

注意:过犹不及,不要将本地化等待时长延长地过长,导致因为大量的等待时长,使得 Spark 作业的运行时间反而增加了。

Sparkローカリゼーション待機時間の設定は次のとおりです。

val conf = new SparkConf().set("spark.locality.wait", "6")

おすすめ

転載: blog.csdn.net/weixin_43520450/article/details/108649183