スパークシリーズ(3) - 柔軟なデータがRDDSを設定し、

データは、弾性RDDSを設定し、

、RDDプロフィール

RDD 弾力性のある分散型データセットと呼ばれる、スパークは読み取り専用で、最も基本的なデータの抽象化、である、パーティションのレコードを設定し、スプーリングは、外部RDDまたは別によって設定されたデータから変換することができ、それは次の特徴があります。

  • 1つまたは複数のパーティション(パーティション)組成物によるRDD。RDDのために、各パーティションは、コンピューティング・タスクによって処理され、ユーザが作成したパーティションの数を指定することができる場合RDD、指定されていない場合、デフォルトのCPUを使用して、プログラムに割り当てられたコアの数。
  • 計算RDDは、パーティションを算出する機能を有しています。
  • RDDは、互いの間の依存関係が保存されます各変換のRDDは、新たな依存関係を生成します、組み立てラインのように、このRDD間の依存関係。区分データ損失の後部に、パーティションは、データ依存ではなく、すべてのパーティションのRDD再計算される再計算することができる失われました。
  • キーと値RDDタイプも仕切りデータが現在HashPartitioner(によるハッシュ分割)とRangeParationer(範囲パーティション)支持スパークに格納されている決定するためのパーティション分割(パーティ)を有しています。
  • 各パーティション(好ま位置)の優先度を記憶する優先順位リスト(オプション)。HDFSファイルの場合、このリストの保存は、コンピューティングタスクが割り当てられますよう「モバイルデータがより良いモバイルコンピューティングである」という概念に基づいて各パーティションのブロックは、タスクのスケジューリング時間を作るスパーク場所ですブロックを対処すべきメモリ位置。

RDD[T] 偏相関抽象クラスコードを次のように:

// 由子类实现以计算给定分区
def compute(split: Partition, context: TaskContext): Iterator[T]

// 获取所有分区
protected def getPartitions: Array[Partition]

// 获取所有依赖关系
protected def getDependencies: Seq[Dependency[_]] = deps

// 获取优先位置列表
protected def getPreferredLocations(split: Partition): Seq[String] = Nil

// 分区器 由子类重写以指定它们的分区方式
@transient val partitioner: Option[Partitioner] = None

第二に、RDDを作成

次のようにRDDを作成する2つの方法は、それぞれ、があります。

2.1既存のコレクションによって作成されました

ここでの使用spark-shell、次のように試験開始コマンドは次のとおりです。

spark-shell --master local[4]

スタートspark-shell、プログラムが自動的にアプリケーション・コンテキストを作成し、同等のScalaは、次の文を実行しました。

val conf = new SparkConf().setAppName("Spark shell").setMaster("local[4]")
val sc = new SparkContext(conf)

指定されていない場合は、既存のRDDによって作成されたコレクションを作成するときには、パーティションの数を指定することができ、プログラムに割り当てられたCPUコアの数が使用されます。

val data = Array(1, 2, 3, 4, 5)
// 由现有集合创建 RDD,默认分区数为程序所分配到的 CPU 的核心数
val dataRDD = sc.parallelize(data) 
// 查看分区数
dataRDD.getNumPartitions
// 明确指定分区数
val dataRDD = sc.parallelize(data,2)

次のように実行結果は以下のとおりです。

https://github.com/heibaiying

2.2参照データセット、外部ストレージシステム

参照データセット、外部ストレージシステムは、例えば、ローカル・ファイル・システムは、HDFS、HBaseのHadoopののInputFormatまたは任意のデータソースをサポートします。

val fileRDD = sc.textFile("/usr/file/emp.txt")
// 获取第一行文本
fileRDD.take(1)

外部ストレージ・システムを使用する場合は、以下の点に注意してください。

  • データをクラスタ環境でのローカルファイルシステムから読み込まれた場合、そのファイルは、クラスタ内のすべてのマシン上に存在しなければならない必要とし、同じパス。
  • Supportディレクトリ・パス、圧縮ファイルのサポートは、ワイルドカードの使用をサポートしています。

2.3テキストファイル&wholeTextFiles

どちらも、外部ファイルを読み込むために使用されるが、フォーマットが異なる返却することができます。

  • テキストファイル:返される形式RDD[String]、リターンは、ファイルの内容、RDD要素がデータの各ラインに対応するということです。
  • wholeTextFiles:返される形式RDD[(String, String)]、タプル最初のパラメータはファイルパスで、2番目のパラメータは、文書の内容です。
  • 両方のパーティションの最小数を制御するための第2パラメータを提供します。
  • HDFSからファイルを読み込むとき、スパークは、各ブロック用のパーティションを作成します。
def textFile(path: String,minPartitions: Int = defaultMinPartitions): RDD[String] = withScope {...}
def wholeTextFiles(path: String,minPartitions: Int = defaultMinPartitions): RDD[(String, String)]={..}

第三に、動作RDD

:RDDは、二つの動作の種類をサポート変換(変換、既存のデータセットからのデータの新しいセットを作成する)とアクション(値を算出した後、データセット上で実行されているドライバに戻ったが)。RDDのすべての変換操作は、彼らはただの変換操作はすぐに実行されていないだけ遭遇覚えて、不活性であるアクションが本当に関数型プログラミングの遅延評価と同様の動作、後に計算されます。

val list = List(1, 2, 3)
// map 是一个 transformations 操作,而 foreach 是一个 actions 操作
sc.parallelize(list).map(_ * 10).foreach(println)
// 输出: 10 20 30

第四に、RDDキャッシュ

4.1キャッシュレベル

一つの理由スパークはRDDキャッシュをサポートして非常に高速です。キャッシュの成功の後、操作後のデータセットを使用している場合は、キャッシュから直接取得されます。キャッシュはまた、損失のリスクですが、理由はRDD間の依存関係のがパーティションのキャッシュデータが失われた場合、再パーティションにのみ必要を計算することができます。

スパークは、複数のキャッシュレベルをサポートしています。

ストレージレベル<BR/>(ストレージレベル) 意味(意味)
MEMORY_ONLY デフォルトのキャッシュレベル、形式で保存されたRDDは、JVMにJavaオブジェクトをデシリアライズ。メモリ容量が不足している場合は、パーティションのデータの一部がキャッシュされることはありません。
MEMORY_AND_DISK フォームのデシリアライズJavaで保存されたRDDは、JVMオブジェクト。メモリ容量が不足している場合は、これらのパーティションを使用する必要がある場合、地区はデータをディスクにキャッシュされませんが、ディスクから読み取ります。
MEMORY_ONLY_SER<BR/> RDDは、Javaオブジェクトの配列の形で(バイト配列のパーティションごとに)保存されました。この方法では、非直列化されたオブジェクトよりもストレージ容量を節約できますが、CPUを読んだとき、計算負荷が増加します。唯一のJavaとScalaのをサポートしています。
MEMORY_AND_DISK_SER<BR/> 同様にMEMORY_ONLY_SER、しかし、オーバーフロー・パーティションのデータを再計算するときにそれらを使用するのではなく、ディスクに保存されています。唯一のJavaとScalaのをサポートしています。
DISK_ONLY RDDディスクにのみキャッシュ
MEMORY_ONLY_2、<BR/> MEMORY_AND_DISK_2など 機能の対応するレベル上記と同じですが、クラスタの各パーティションの両方のノードのコピーを作成します。
OFF_HEAP MEMORY_ONLY_SER似ていますが、データは、ヒープ内の外部メモリに保存されています。これは、外部ヒープメモリを有効にする必要があります。

ヒープメモリ構成の外に開始し、2つのパラメータが必要です。

  • spark.memory.offHeap.enabled:外側のヒープメモリを開くには、デフォルトはfalseで、これをtrueに設定する必要があるかどうか。
  • spark.memory.offHeap.size:外部メモリヒープサイズは、デフォルト値は0で、正の値に設定する必要があります。

4.2を使用するキャッシュ

そこデータキャッシュの二つの方法があります:persistcachecacheまた、内部で呼ばれpersist、それはpersist、特別な形式に相当しますpersist(StorageLevel.MEMORY_ONLY)例としては、次のとおりです:

// 所有存储级别均定义在 StorageLevel 对象中
fileRDD.persist(StorageLevel.MEMORY_AND_DISK)
fileRDD.cache()

4.3キャッシュを削除します

スパークは、自動的に各ノードのキャッシュの使用状況を監視し、最低使用頻度(LRU)ルールに従って古いデータ・パーティションを削除します。もちろん、あなたも使用することができRDD.unpersist()、手動で削除する方法を。

第五に、シャッフルを理解します

5.1シャッフル紹介

スパークでは、パーティションに対応するタスクは、通常、パーティション間でデータを操作しないでください。あなたが発生した場合でも、reduceByKey他の操作を、スパークは、すべてのパーティションからデータを読み込み、すべてのキーのすべての値を見つけ、その後、呼び出された各キーのための最終結果を計算するために一緒に集約しなければなりませんShuffle

https://github.com/heibaiying

5.2シャッフルの影響

シャッフルはそれは多くの場合、データノード間で動作するため、高価な操作であり、これは、ディスクI / O、ネットワークI / O、およびデータのシリアル化を伴います。彼らは一時的にネットワークの伝送に必要なデータを格納するためのヒープメモリを使用しているため、一部シャッフル動作も、ヒープメモリを大量に消費します。シャッフルもスパーク1.3から開始し、ディスク上の中間多数のファイルを生成し、対応するRDDとガベージコレクションが計算にシャッフルファイルを再作成を回避するために行われるまで、これらのファイルが使用中でもはや保存されません。これらの長期保存RDDへのアプリケーション参照は、ガベージコレクションが実行時間の長いスパークジョブがディスクスペースの多くを取ることを意味し、時間の長い期間、後に行うことができる場合は、通常使用することができますspark.local.dirこれらの一時ファイルを指定するパラメータを格納ディレクトリ。

シャッフルで5.3業績

比較的大きい、それはの使用に特別な注意を払う必要があり、次のようにシャッフルを生じることによるパフォーマンスへの影響に操作をシャッフル:

  • これは、操作を再分割に関する:などrepartitioncoalesce
  • 所有涉及到 ByKey 的操作:如 groupByKeyreduceByKey,但 countByKey 除外;
  • 联结操作:如 cogroupjoin

五、宽依赖和窄依赖

RDD 和它的父 RDD(s) 之间的依赖关系分为两种不同的类型:

  • 窄依赖 (narrow dependency):父 RDDs 的一个分区最多被子 RDDs 一个分区所依赖;
  • 宽依赖 (wide dependency):父 RDDs 的一个分区可以被子 RDDs 的多个子分区所依赖。

如下图,每一个方框表示一个 RDD,带有颜色的矩形表示分区:

https://github.com/heibaiying

区分这两种依赖是非常有用的:

  • 首先,窄依赖允许在一个集群节点上以流水线的方式(pipeline)对父分区数据进行计算,例如先执行 map 操作,然后执行 filter 操作。而宽依赖则需要计算好所有父分区的数据,然后再在节点之间进行 Shuffle,这与 MapReduce 类似。
  • 窄依赖能够更有效地进行数据恢复,因为只需重新对丢失分区的父分区进行计算,且不同节点之间可以并行计算;而对于宽依赖而言,如果数据丢失,则需要对所有父分区数据进行计算并再次 Shuffle。

六、DAG的生成

RDD(s) 及其之间的依赖关系组成了 DAG(有向无环图),DAG 定义了这些 RDD(s) 之间的 Lineage(血统) 关系,通过血统关系,如果一个 RDD 的部分或者全部计算结果丢失了,也可以重新进行计算。那么 Spark 是如何根据 DAG 来生成计算任务呢?主要是根据依赖关系的不同将 DAG 划分为不同的计算阶段 (Stage):

  • 对于窄依赖,由于分区的依赖关系是确定的,其转换操作可以在同一个线程执行,所以可以划分到同一个执行阶段;
  • あなたは、ステージを再描画幅広い経験に頼る必要があるので、ワイド依存に起因シャッフルの存在にするために、親のみRDD(複数可)の後に、次の計算を開始する前に、完全なシャッフルを処理されています。

https://github.com/heibaiying

参考資料

  1. ZHANGアンインサイド駅スパーク:原則[M]機械プレス2015年9月1日のコアアーキテクチャの設計と実装のスパークの詳細な分析。
  2. EETプログラミングガイド
  3. RDD:メモリベースのコンピューティングクラスタのフォールトトレランス抽象

もっと大きなデータ系列は、GitHubのオープンソースプロジェクトを見つけることができますビッグデータははじめに

おすすめ

転載: blog.51cto.com/14183932/2438759