Sparkの基本的な研究ノート21:RDDチェックポイントと共有変数

ゼロ、この講義の学習目標

  1. RDDチェックポイントメカニズムの特性と有用性を理解する
  2. 共有変数のタイプ、特性、および使用法を理解する

1.RDDチェックポイント

(1)RDDチェックポイントメカニズム

  • RDDチェックポイントメカニズム(チェックポイント)は、RDDデータのスナップショットを作成するのと同じです。これにより、頻繁に使用されるRDDを特定のファイルシステム、できればHDFSなどの共有ファイルシステムにスナップショットできます。マシンの故障によりメモリまたはディスクのRDDデータが失われた場合、RDDの依存関係に基づいて最初から計算を実行しなくても、指定したRDDをスナップショットからすばやく回復できるため、計算効率が大幅に向上します。

(2)RDD永続性との違い

  • cache()またはpersist()は、マシンのローカルメモリまたはディスクにデータを保存します。マシンに障害が発生した場合、データリカバリは実行できませんが、チェックポイントはRDDデータを外部共有ファイルシステム(HDFSなど)に保存します。 、共有ファイルシステムのコピーメカニズムにより、データの信頼性が保証されます。
  • Sparkアプリケーションの実行が終了すると、cache()またはpersist()に保存されているデータは空になりますが、チェックポイントに保存されているデータは影響を受けず、手動で削除しない限り保持されます。したがって、チェックポイントデータは次のSparkアプリケーションで使用できますが、cache()またはpersist()データは現在のSparkアプリケーションでのみ使用できます。

(3)RDDチェックポイントケースのデモンストレーション

  • パッケージにオブジェクトnet.huawei.rdd作成するCheckpointDemo
    ここに画像の説明を挿入
    ここに画像の説明を挿入
package net.huawei.rdd

import org.apache.spark.rdd.RDD
import org.apache.spark.{
    
    SparkConf, SparkContext}

/**
  * 功能:RDD检查点演示
  * 作者:华卫
  * 日期:2022年04月16日
  */
object CheckpointDemo {
    
    
  def main(args: Array[String]): Unit = {
    
    
    // 设置系统属性(本地运行必须设置,否则无权访问HDFS)
    System.setProperty("HADOOP_USER_NAME", "root")
    // 创建SparkConf对象
    val conf = new SparkConf()
    // 设置应用程序名称,可在Spark WebUI里显示
    conf.setAppName("Spark-CheckpointDemo")
    // 设置集群Master节点访问地址
    conf.setMaster("local[2]")
    // 设置测试内存
    conf.set("spark.testing.memory", "2147480000")
    // 基于SparkConf对象创建SparkContext对象,该对象是提交Spark应用程序的入口
    val sc = new SparkContext(conf)

    // 设置检查点数据存储路径
    sc.setCheckpointDir("hdfs://master:9000/spark-ck")
    // 创建模拟数据RDD
    val rdd: RDD[Int] = sc.parallelize(List(1, 1, 2, 3, 5, 8, 13))
    // 过滤结果
    val resultRDD = rdd.filter(_ >= 5)
    // 持久化RDD到内存中
    resultRDD.cache()
    // 将resultRDD标记为检查点
    resultRDD.checkpoint()

    // 第一次行动算子计算时,将把标记为检查点的RDD数据存储到文件系统指定路径中
    val result: String = resultRDD.collect().mkString(", ")
    println(result)
    // 第二次行动算子计算时,将直接从文件系统读取resultRDD数据,而不需要从头计算
    val count = resultRDD.count()
    println(count)

    // 停止Spark容器
    sc.stop()
  }
}
  • 上記のコードは、checkpoint()メソッドを使用してRDDをチェックポイントとしてマークします(マークされるだけで、アクション演算子が実行されます)。最初のアクション計算では、チェックポイントとしてマークされたRDDのデータが、setCheckpointDir()メソッドで指定されたファイルシステムディレクトリにファイルとして保存され、このRDDのすべての親RDD依存関係が削除されます。 RDDが計算され、依存関係に基づいて再計算することなく、データがファイルシステムから直接読み取られます。
  • RDDのデータが永続化されている場合、SparkはチェックポイントとしてマークされたRDDのデータをファイルシステムに書き込むために別のタスクを開始するため、RDDをチェックポイントとしてマークする前にRDDをメモリに永続化することをお勧めします。 〜メモリ内では、データはメモリから直接読み取られ、データ書き込みの効率を向上させるために書き込まれます。そうでない場合、RDDのデータを繰り返し計算する必要があります。
  • データを保存するためのチェックポイントディレクトリを作成します
    ここに画像の説明を挿入
  • プログラムを実行し、コンソールで結果を表示します
    ここに画像の説明を挿入
  • HDFSチェックポイントディレクトリを表示するには、次のコマンドを実行します。hdfs dfs -ls -R /spark-ck
    ここに画像の説明を挿入

2.共有変数

  • 通常、Sparkアプリケーションの実行中、Sparkオペレーターの関数func(map(func)やfilter(func)など)は実行のために複数のリモートワーカーノードに送信されます。オペレーターがA特定のを使用する場合外部变量、変数はワーカーノードの各タスクタスクにコピーされ、変数に対する各タスクタスクの操作は互いに独立しています。変数によって格納されるデータの量が非常に多い場合(大規模なコレクションなど)、ネットワーク送信とメモリのオーバーヘッドが増加します。したがって、Sparkは、ブロードキャスト変数とアキュムレータの2種類の共有変数を提供します。

(1)ブロードキャスト変数

  • ブロードキャスト変数は、変数を各タスクタスクに送信するのではなく、ブロードキャストによって各ワーカーノードのキャッシュに送信することであり、各タスクタスクは変数のデータを共有できます。したがって、ブロードキャスト変数は読み取り専用です。

1.デフォルトで渡される変数

  • 外部変数arrは、map()演算子によって渡される関数で使用されます
    ここに画像の説明を挿入
scala> val arr = Array(1, 2, 3, 4, 5)
scala> val lines = sc.textFile("data.txt")
scala> val result = lines.map((_, arr))
scala> result.collect()
  • 上記のコードでは、map()演算子に渡された関数は(_, arr)実行のためにエグゼキューター側に送信され、変数arrはに送信Worker节点され所有Task任务ます。変数arrを渡すプロセスを次の図に示します。
    ここに画像の説明を挿入
  • arr変数に格納されるデータの量が多いと仮定すると、各タスクタスクはコピー100MBを維持する必要があります。タスクタスクがエグゼキュータで開始されると、エグゼキュータはメモリを消費します。100MB3300MB

2.ブロードキャスト変数を使用する場合の変数の送信

  • ブロードキャスト変数は、実際には通常の変数のカプセル化です。分散関数でvalueは、ブロードキャスト変数の値は、Broadcastオブジェクトのメソッドを介してアクセスできます。
    ここに画像の説明を挿入
  • ブロードキャスト変数を使用して、配列arrをmap()演算子に渡します
    ここに画像の説明を挿入
scala> val arr = Array(1, 2, 3, 4, 5)
scala> val broadcastVar = sc.broadcast(arr)
scala> val lines = sc.textFile("data.txt")
scala> val result = lines.map((_, broadcastVar))
scala> result.collect()
  • 上記のコードは、1回だけ送信され、オブジェクトであるbroadcast()ブロードキャスト変数を返すメソッドを使用して、読み取り専用変数をクラスターに送信(ブロードキャスト)します。ブロードキャストオブジェクトは読み取り専用であり、クラスターの各ワーカーノードにキャッシュされます。次の図に、ブロードキャスト変数を使用した変数送信のフローを示します。broadcastVarorg.apache.spark.broadcast.Broadcast
    ここに画像の説明を挿入
  • ワーカーノードの各タスクタスクは、一意のブロードキャスト変数を共有します。これにより、ネットワーク送信とメモリのオーバーヘッドが大幅に削減されます。
  • 出力結果データ
    ここに画像の説明を挿入

(2)アキュムレータ

1.アキュムレータ機能

  • アキュムレータは、ワーカーノードの値をドライバーに集約する機能を提供します。これを使用して、カウントと合計を実装できます。

2.アキュムレータを使用しないでください

  • 整数の配列を合計する
    ここに画像の説明を挿入
  • 上記のコードは、sum変数Driverがで定義されており、累積演算sum = sum + xがに送信されるExecutorため、出力結果が正しくありません。

3.アキュムレータを使用する

  • 整数の配列を合計する
    ここに画像の説明を挿入
scala> val myacc = sc.longAccumulator("My Accumulator") // 声明累加器
scala> val rdd = sc.makeRDD(Array(1, 2, 3, 4, 5))
scala> rdd.foreach(x => myacc.add(x)) // 向累加器添加值
scala> println("sum = " + myacc.value) // 在Driver端输出结果
  • 上記のコードは、SparkContextオブジェクトのメソッドを呼び出すことによってタイプlongAccumulator ()のアキュムレータを作成します。Longデフォルトの初期値は0です。タイプのアキュムレータは、doubleAccumulator()メソッドを使用して作成することもできます。Double
  • Driver端定义アキュムレータは、、にのみ存在できますExecutor端更新エグゼキュータ側はアキュムレータの値を読み取ることができないため、属性Driver端を使用して読み取る必要があります。value

おすすめ

転載: blog.csdn.net/howard2005/article/details/124096794