スパークEET:スパークAPI - スパークEET

、RDDの概要

1.1 RDDとは何ですか?

RDDは(弾性分散データセット)と呼ばれる弾性分散データセットを最も基本的なデータ抽象スパークで表し、並列コンピューティング要素のセットを、パーティション、不変。有するRDD特性データフローモデル:自動フォールトトレランス、位置認識型スケジューリングおよびスケーラビリティ。RDDは、ワーキングメモリに明示的にキャッシュされた設定した場合、ユーザは複数のクエリを実行することができ、後続の問合せが大幅にクエリの速度を向上させる作業セットを、再利用することができます。

1.2 RDDプロパティ

スライス(パーティション)の基本単位(1)、すなわちデータセット。RDDのために、各スライスは、コンピューティングタスクを処理すること、および粒子サイズ並列計算を決定するであろう。指定されていない場合、ユーザはRDD RDDの作成におけるスライスの数を指定することができ、それが値をデフォルト設定されます。デフォルト値は、CPUコアのプログラムに割り当てられた番号です。

(2)各パーティションの計算機能。スパークRDD計算は、関数のそれぞれは、RDDは、この目的を達成する計算するために、スライス単位に基づいています。イテレータは機能複合体を計算し、各計算の結果を保存する必要はありません。

(3)RDD間の依存関係。RDD各変換器が新しいRDDを生成し、それが前部と後部との間のRDD同じ依存性のような行を形成することになります。パーティションのデータ損失の一部は、スパークは、この依存関係によって失われたパーティションのデータを再計算することができたときではなく、すべてのパーティションのRDDが再計算されました。

(4)パーティション分割、すなわちRDDスライス機能。現在フラグメンテーション関数の二種類に実装スパークハッシュベースHashPartitioner、他基づくRangePartitionerの範囲です。唯一のキーと値でRDDのために、RDD Parititioner非キー値の値がNone、パーティショナを持つことになります。パーティショナ機能は断片RDD自体の数を決定するだけでなく、とき、親RDDシャッフル出力フラグメントの数を決定していないだけ。

(5)各パーティション(好ましい位置)のメモリアクセス優先順位のリスト。HDFSファイルの場合、このリストの保存は、各パーティションのブロック位置です。タスクのスケジューリングを実行するとき、「モバイルコンピューティングほど良好で移動データ」の概念によれば、スパークは、タスクが処理されるべきデータブロックの格納位置に割り当て算出することが可能となります。

1.3 WORDCOUNT粗図RDD

 

 どのhello.txt

 

 

二、RDDの道を作成します

ファイルを読み込むことで生成された2.1

ローカルファイルシステムを含むデータ記憶システムの外部のセット、ならびに等HDFS、カサンドラ、HBaseのようなすべてのサポートのHadoopデータセットによって作成

スカラ> valのファイル= sc.textFile( "/火花/ hello.txt")

  

並列化の方法によって作成された2.2 RDD

既存のスカラ座のセットで作成されました。

スカラ>ヴァル配列=配列(1,2,3,4,5)
配列:配列[INT] =配列(1、2、3、4、5)

スカラ>ヴァルRDD = sc.parallelize(アレイ)
RDD:ORG .apache.spark.rdd.RDD [INT] = ParallelCollectionRDD [27]に並列化で<コンソール>:26 

スカラ>

  

 

 

 

 

2.3その他の方法

あなたはその上の別の運用データベースとを読み取ることができます。また、生成することができますRDDを。

他でRDD RDDから変換しました。

 

三、RDDプログラミングAPI

変革と行動:スパークには2つのタイプ(オペレータ)の操作をサポートしています

3.1変換

既存のRDDの主な仕事は、他のRDDを生成することです。形質転換遅延特性(遅延ロード)変換演算子のコードが実際に実行されません。コードが実際に実行されるとき、私たちは、内部のオペレータの操作に遭遇した場合のみ。この設計は、Sparkは、より効率的に実行することができます。

一般的に使用される変換

変更

意味

マップ(FUNC)

新しいRDD、RDDは、変換関数func後の各入力要素の組成によって返します。

フィルタ(FUNC)

入力要素FUNC組成がtrueの後にそれは計算する関数によって返された新しいRDD、RDDを返します。

flatMap(FUNC)

(それはむしろ、単一の要素よりも、配列を返すべき機能)を同様のマップが、各入力要素は、ゼロ以上の出力要素にマッピングすることができます

mapPartitions(FUNC)

FUNC関数型はイテレータ[T] =>イテレータ[U]でなければならない場合、同様のマップが、しかしこのようRDD型Tを実行して、RDDの各スライス上で独立して実行

mapPartitionsWithIndex(FUNC)

操作の種類RDD T上のように、関数func型がなければならないので、同様のmapPartitionsが、指標パラメータの値とFUNC整数は、スライスを示し

(INT、Interator [T])=>イテレータ[U]

サンプル(にwithReplacement、分数、種子)

比率指定画分に応じたサンプルデータは、シード乱数発生器のシードを指定するため、交換する乱数を使用するかどうかを選択することができ

労働組合(otherDataset)

ソースRDDとRDDのパラメータと要件は、新しいRDDリターンを設定した後、

交差点(otherDataset)

RDDソースパラメータとの交差点の後に新しいRDD RDDを返します。

異なる([numTasks]))

ソースの後RDDは新しいRDDへの再復帰しました

groupByKey([numTasks])

(K、V)RDD呼の、それはRDDの(K、イテレータ[V])を返しますで

reduceByKey(FUNC、[numTasks])

RDDコールの(V K)、RDDの(V Kなど)を返し、指定された機能を低下させるが、同じキー値が同様groupByKeyと共に重合さで、タスクの数が第2によって実行することができる減らしますオプションのパラメータを設定します

aggregateByKey(zeroValue)(seqOp、combOp、[numTasks])

(0)(_ + _、_ _ +)RDD kに/ yが動作aggregateByKey:次に交互例の各初期値を保持する全重合重合にパーティションを押し

sortByKey([昇順]、[numTasks])

呼び出しRDDの(V K)において、Kは、順序付きインターフェースがソートRDDの鍵(K、V)によれば返し実装しなければなりません

SORTBY(FUNC、[昇順]、[numTasks])

そしてsortByKey似ていますが、より柔軟な最初の引数は、第二は、デフォルトでは第三偽ソートパーティション元RDDと同じ後に逆の順序でソートする方法でどのように基づいています

参加(otherDataset、[numTasks])

RDD呼のタイプ(K、V)、及び(K、W)において(K、(V、W))が内部接続RDD(の交差点)に対応一緒に同じキーに対応するすべての要素を返します

コグループ(otherDataset、[numTasks])

RDD呼のタイプ(K、V)、及び(K、W)において、それは返し(K、(反復処理可能<V>を、反復処理可能では<W>))RDDを入力します

デカルト(otherDataset)

K / Vの数にRDD 2直積

パイプ(コマンド、[envvarsが])

外部プログラムを呼び出します

合体(numPartitions )   

最初のパラメータの再ゾーニングは、第二の引数偽シャッフルデフォルトパーティションが少ない偽少ない真のマルチマルチパーティションパーティションパーティションになったか否か、領域の数を分割することです

ディストリビューション(numPartitions)

配分は、パラメータをシャッフルしなければならないゾーンの数が少ない点に増大しています

repartitionAndSortWithinPartitions(パーティション)

前高効率並べ替えよりも動作するように再分配の+ソートK RDD / V・パーティション

foldByKey(zeroValue)(seqOp)

この関数は、K / Vは重合例である第2ブラケット関数Vの各パラメータ値に適用される第1ブラケット集合体と同様に折り畳まマージ処理を行います。_ _ +

combineByKey

合并相同的key的值 rdd1.combineByKey(x => x, (a: Int, b: Int) => a + b, (m: Int, n: Int) => m + n)

partitionBy(partitioner)

对RDD进行分区  partitioner是分区器 例如new HashPartition(2

cache

RDD缓存,可以避免重复计算从而减少时间,区别:cache内部调用了persist算子,cache默认就一个缓存级别MEMORY-ONLY ,而persist则可以选择缓存级别

persist

 

 

Subtract(rdd)

返回前rdd元素不在后rdd的rdd

leftOuterJoin

leftOuterJoin类似于SQL中的左外关联left outer join,返回结果以前面的RDD为主,关联不上的记录为空。只能用于两个RDD之间的关联,如果要多个RDD关联,多关联几次即可。

rightOuterJoin

rightOuterJoin类似于SQL中的有外关联right outer join,返回结果以参数中的RDD为主,关联不上的记录为空。只能用于两个RDD之间的关联,如果要多个RDD关联,多关联几次即可

subtractByKey

substractByKey和基本转换操作中的subtract类似只不过这里是针对K的,返回在主RDD中出现,并且不在otherRDD中出现的元素

3.2 Action

触发代码的运行,我们一段spark代码里面至少需要有一个action操作。

常用的Action:

动作

含义

reduce(func)

通过func函数聚集RDD中的所有元素,这个功能必须是课交换且可并联的

collect()

在驱动程序中,以数组的形式返回数据集的所有元素

count()

返回RDD的元素个数

first()

返回RDD的第一个元素(类似于take(1))

take(n)

返回一个由数据集的前n个元素组成的数组

takeSample(withReplacement,num, [seed])

返回一个数组,该数组由从数据集中随机采样的num个元素组成,可以选择是否用随机数替换不足的部分,seed用于指定随机数生成器种子

takeOrdered(n[ordering])

 

saveAsTextFile(path)

将数据集的元素以textfile的形式保存到HDFS文件系统或者其他支持的文件系统,对于每个元素,Spark将会调用toString方法,将它装换为文件中的文本

saveAsSequenceFile(path

将数据集中的元素以Hadoop sequencefile的格式保存到指定的目录下,可以使HDFS或者其他Hadoop支持的文件系统。

saveAsObjectFile(path

 

countByKey()

针对(K,V)类型的RDD,返回一个(K,Int)的map,表示每一个key对应的元素个数。

foreach(func)

在数据集的每一个元素上,运行函数func进行更新。

aggregate

先对分区进行操作,在总体操作

reduceByKeyLocally

 

lookup

 

top

 

fold

 

foreachPartition

 

 

 

3.3 Spark WordCount代码编写

使用maven进行项目构建

(1)使用scala进行编写

查看官方网站,需要导入2个依赖包

 

 

 

详细代码

SparkWordCountWithScala.scala

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

object SparkWordCountWithScala {
  def main(args: Array[String]): Unit = {

    val conf = new SparkConf()
    /**
      * 如果这个参数不设置,默认认为你运行的是集群模式
      * 如果设置成local代表运行的是local模式
      */
    conf.setMaster("local")
    //设置任务名
    conf.setAppName("WordCount")
    //创建SparkCore的程序入口
    val sc = new SparkContext(conf)
    //读取文件 生成RDD
    val file: RDD[String] = sc.textFile("E:\\hello.txt")
    //把每一行数据按照,分割
    val word: RDD[String] = file.flatMap(_.split(","))
    //让每一个单词都出现一次
    val wordOne: RDD[(String, Int)] = word.map((_,1))
    //单词计数
    val wordCount: RDD[(String, Int)] = wordOne.reduceByKey(_+_)
    //按照单词出现的次数 降序排序
    val sortRdd: RDD[(String, Int)] = wordCount.sortBy(tuple => tuple._2,false)
    //将最终的结果进行保存
    sortRdd.saveAsTextFile("E:\\result")

    sc.stop()
  }

  

运行结果

 

 

 

3.4 WordCount执行过程图

 

 

 

 

 

 

 

 

 

四、RDD的宽依赖和窄依赖

4.1 RDD依赖关系的本质内幕

由于RDD是粗粒度的操作数据集,每个Transformation操作都会生成一个新的RDD,所以RDD之间就会形成类似流水线的前后依赖关系;RDD和它依赖的父RDD(s)的关系有两种不同的类型,即窄依赖(narrow dependency)和宽依赖(wide dependency)。如图所示显示了RDD之间的依赖关系。

 

 

 

从图中可知:

窄依赖:是指每个父RDD的一个Partition最多被子RDD的一个Partition所使用,例如map、filter、union等操作都会产生窄依赖;(独生子女)

宽依赖:是指一个父RDD的Partition会被多个子RDD的Partition所使用,例如groupByKey、reduceByKey、sortByKey等操作都会产生宽依赖;(超生)

需要特别说明的是对join操作有两种情况:

(1)图中左半部分join:如果两个RDD在进行join操作时,一个RDD的partition仅仅和另一个RDD中已知个数的Partition进行join,那么这种类型的join操作就是窄依赖,例如图1中左半部分的join操作(join with inputs co-partitioned);

(2)图中右半部分join:其它情况的join操作就是宽依赖,例如图1中右半部分的join操作(join with inputs not co-partitioned),由于是需要父RDD的所有partition进行join的转换,这就涉及到了shuffle,因此这种类型的join操作也是宽依赖。

总结:

在这里我们是从父RDD的partition被使用的个数来定义窄依赖和宽依赖,因此可以用一句话概括下:如果父RDD的一个Partition被子RDD的一个Partition所使用就是窄依赖,否则的话就是宽依赖。因为是确定的partition数量的依赖关系,所以RDD之间的依赖关系就是窄依赖;由此我们可以得出一个推论:即窄依赖不仅包含一对一的窄依赖,还包含一对固定个数的窄依赖。

一对固定个数的窄依赖的理解:即子RDD的partition对父RDD依赖的Partition的数量不会随着RDD数据规模的改变而改变;换句话说,无论是有100T的数据量还是1P的数据量,在窄依赖中,子RDD所依赖的父RDD的partition的个数是确定的,而宽依赖是shuffle级别的,数据量越大,那么子RDD所依赖的父RDD的个数就越多,从而子RDD所依赖的父RDD的partition的个数也会变得越来越多。

 

4.2 依赖关系下的数据流视图

 

 

在spark中,会根据RDD之间的依赖关系将DAG图(有向无环图)划分为不同的阶段,对于窄依赖,由于partition依赖关系的确定性,partition的转换处理就可以在同一个线程里完成,窄依赖就被spark划分到同一个stage中,而对于宽依赖,只能等父RDD shuffle处理完成后,下一个stage才能开始接下来的计算。

因此spark划分stage的整体思路是:从后往前推,遇到宽依赖就断开,划分为一个stage;遇到窄依赖就将这个RDD加入该stage中。因此在图2中RDD C,RDD D,RDD E,RDDF被构建在一个stage中,RDD A被构建在一个单独的Stage中,而RDD B和RDD G又被构建在同一个stage中。

在spark中,Task的类型分为2种:ShuffleMapTaskResultTask

简单来说,DAG的最后一个阶段会为每个结果的partition生成一个ResultTask,即每个Stage里面的Task的数量是由该Stage中最后一个RDD的Partition的数量所决定的!而其余所有阶段都会生成ShuffleMapTask;之所以称之为ShuffleMapTask是因为它需要将自己的计算结果通过shuffle到下一个stage中;也就是说上图中的stage1和stage2相当于mapreduce中的Mapper,而ResultTask所代表的stage3就相当于mapreduce中的reducer。

在之前动手操作了一个wordcount程序,因此可知,Hadoop中MapReduce操作中的Mapper和Reducer在spark中的基本等量算子是map和reduceByKey;不过区别在于:Hadoop中的MapReduce天生就是排序的;而reduceByKey只是根据Key进行reduce,但spark除了这两个算子还有其他的算子;因此从这个意义上来说,Spark比Hadoop的计算算子更为丰富。

 

 

おすすめ

転載: www.cnblogs.com/tesla-turing/p/11489203.html