ビッグデータの学習ルートは弾力性の分散型データセットのRDDを共有良いプログラマは、RDDはスパークが表す最も基本的なデータ抽象化され、分散データ・セットと呼ばれ、RDD(弾力性のある分散型データセット)を定義した(データおよびメタデータ)不変の、あなたが分割することができ要素内の並列コンピューティング・コレクション。
RDDは特徴:自動フォールトトレランス、位置認識スケジューリングおよびスケーラビリティを
RDDプロパティ
1.スライス
データセットの基本単位。RDDのために、各スライスは、コンピューティングタスクを処理すること、および粒子サイズ並列計算を決定するであろう。指定されていない場合、ユーザはRDD RDDの作成におけるスライスの数を指定することができ、それが値をデフォルト設定されます。デフォルト値は、CPUコアのプログラムに割り当てられた番号です。
2.関数は、各パーティションに対して計算されます。
スパークRDD計算は、関数のそれぞれは、RDDは、この目的を達成する計算するために、スライス単位に基づいています。イテレータは機能複合体を計算し、各計算の結果を保存する必要はありません。
3.RDD間の依存関係。
RDD各変換器が新しいRDDを生成し、それが前部と後部との間のRDD同じ依存性のような行を形成することになります。
フォールトトレランス:パート分割データの損失は、スパークは、すべてのパーティションのRDDが再計算されたのではなく、この依存関係によって失われたパーティションのデータを再計算することができたとき。
4. Aパーティショナ、パーティ
すなわち、RDDスライス機能。現在フラグメンテーション関数の二種類に実装スパークハッシュベースHashPartitioner、他基づくRangePartitionerの範囲です。のみRDDのキーと値のために、RDD Parititioner非キー値の値がNone、パーティショナを持つことになります。パーティショナ機能は断片RDD自体の数を決定するだけでなく、とき、親RDDシャッフル出力フラグメントの数を決定していないだけ。
5.リスト
(好ましい位置)のそれぞれのパーティションのメモリアクセス優先順位。 - >近接原理
HDFSファイルのため、このリストの保存は、各パーティションのブロック位置です。タスクのスケジューリングを実行するとき、「モバイルコンピューティングほど良好で移動データ」の概念によれば、スパークは、タスクが処理されるべきデータブロックの格納位置に割り当て算出することが可能となります。
RDDタイプ
1.Transformation - >計算用記録(記録パラメータの算出方法)
変更 |
意味 |
マップ(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、イテレータ[T])=>イテレータ[U] |
サンプル(にwithReplacement、分数、種子) |
比率指定画分に応じたサンプルデータは、シード乱数発生器のシードを指定するため、交換する乱数を使用するかどうかを選択することができ |
労働組合(otherDataset) |
ソースRDDとRDDのパラメータと要件は、新しいRDDリターンを設定した後、 |
交差点(otherDataset) 差分 - > SET違い |
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]) |
|
sortByKey([昇順]、[numTasks]) |
呼び出しRDDの(V K)において、Kは、順序付きインターフェースがソートRDDの鍵(K、V)によれば返し実装しなければなりません |
SORTBY(FUNC、[昇順]、[numTasks]) |
そしてsortByKey似ていますが、より柔軟 |
参加(otherDataset、[numTasks]) |
RDD呼のタイプ(K、V)、及び(K、W)の一方の全ての要素を返し、同じキーは、(K、(V、W))を一緒にRDDに対応 |
コグループ(otherDataset、[numTasks]) |
在类型为(K,V)和(K,W)的RDD上调用,返回一个(K,(Iterable<V>,Iterable<W>))类型的RDD |
cartesian(otherDataset) |
笛卡尔积 |
pipe(command, [envVars]) |
|
coalesce(numPartitions) |
|
repartition(numPartitions) |
重新分区 |
repartitionAndSortWithinPartitions(partitioner) |
2.Action -> 触发生成job(一个job对应一个action算子)
动作 |
含义 |
reduce(func) |
通过func函数聚集RDD中的所有元素,这个功能必须是可交换且可并联的 |
collect() |
在驱动程序中,以数组的形式返回数据集的所有元素 |
count() |
返回RDD的元素个数 |
first() |
返回RDD的第一个元素(类似于take(1)) |
take(n) |
取数据集的前n个元素组成的数组 |
takeSample(withReplacement,num, [seed]) |
返回一个数组,该数组由从数据集中随机采样的num个元素组成,可以选择是否用随机数替换不足的部分,seed用于指定随机数生成器种子 |
takeOrdered(n, [ordering]) |
takeOrdered和top类似,只不过以和top相反的顺序返回元素 |
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进行更新。 |
创建RDD
Linux进入sparkShell:
/usr/local/spark.../bin/spark-shell \
--master spark://hadoop01:7077 \
--executor-memory 512m \
--total-executor-cores 2
或在Maven下:
object lx03 { def main(args: Array[String]): Unit = { val conf : SparkConf = new SparkConf() .setAppName("SparkAPI") .setMaster("local[*]") val sc: SparkContext = new SparkContext(conf) //通过并行化生成rdd val rdd1: RDD[Int] = sc.parallelize(List(24,56,3,2,1)) //对add1的每个元素乘以2然后排序 val rdd2: RDD[Int] = rdd1.map(_ * 2).sortBy(x => x,true) println(rdd2.collect().toBuffer) //过滤出大于等于10的元素 // val rdd3: RDD[Int] = rdd2.filter(_ >= 10) // println(rdd3.collect().toBuffer) } |
练习2
val rdd1 = sc.parallelize(Array("a b c", "d e f", "h i j")) //将rdd1里面的每一个元素先切分在压平 val rdd2 = rdd1.flatMap(_.split(' ')) rdd2.collect //复杂的: val rdd1 = sc.parallelize(List(List("a b c", "a b b"), List("e f g", "a f g"), List("h i j", "a a b"))) //将rdd1里面的每一个元素先切分在压平 val rdd2 = rdd1.flatMap(_.flatMap(_.split(" "))) |
练习3
val rdd1 = sc.parallelize(List(5, 6, 4, 3)) val rdd2 = sc.parallelize(List(1, 2, 3, 4)) //求并集 val rdd3 = rdd1.union(rdd2) //求交集 val rdd4 = rdd1.intersection(rdd2) //去重 rdd3.distinct.collect rdd4.collect |
练习4
val rdd1 = sc.parallelize(List(("tom", 1), ("jerry", 3), ("kitty", 2))) val rdd2 = sc.parallelize(List(("jerry", 2), ("tom", 1), ("shuke", 2))) //求join val rdd3 = rdd1.join(rdd2) -> 相同的key组成新的key,value //结果: Array[(String,(Int,Int))] = Array((tom,(1,1)),(jerry,(3,2))) rdd3.collect //求左连接和右连接 val rdd3 = rdd1.leftOuterJoin(rdd2) rdd3.collect val rdd3 = rdd1.rightOuterJoin(rdd2) rdd3.collect //求并集 val rdd4 = rdd1 union rdd2 //按key进行分组 rdd4.groupByKey rdd4.collect //分别用groupByKey和reduceByKey实现单词计数 val rdd3 = rdd1 union rdd2 rdd3.groupByKey().mapValues(_.sum).collect rdd3.reduceByKey(_+_).collect |
groupByKey和reduceByKey的区别
reduceByKey算子比较特殊,它首先会进行局部聚合,再全局聚合,我们只需要传一个局部聚合的函数就可以了
练习5
val rdd1 = sc.parallelize(List(("tom", 1), ("tom", 2), ("jerry", 3), ("kitty", 2))) val rdd2 = sc.parallelize(List(("jerry", 2), ("tom", 1), ("shuke", 2))) //cogroup val rdd3 = rdd1.cogroup(rdd2) //注意cogroup与groupByKey的区别 rdd3.collect val rdd1 = sc.parallelize(List(1, 2, 3, 4, 5)) //reduce聚合 val rdd2 = rdd1.reduce(_ + _) //按value的降序排序 val rdd5 = rdd4.map(t => (t._2, t._1)).sortByKey(false).map(t => (t._2, t._1)) rdd5.collect //笛卡尔积 val rdd3 = rdd1.cartesian(rdd2) |
计算元素个数
scala> val rdd1 = sc.parallelize(List(2,3,1,5,7,3,4)) rdd1: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[0] at parallelize at <console>:27 scala> rdd1.count res0: Long = 7 |
top先升序排序在取值
scala> rdd1.top(3) res1: Array[Int] = Array(7, 5, 4) scala> rdd1.top(0) res2: Array[Int] = Array() scala> rdd1.top(100) res3: Array[Int] = Array(7, 5, 4, 3, 3, 2, 1) |
take原集合前N个,有几个取几个
scala> rdd1.take(3) res4: Array[Int] = Array(2, 3, 1) scala> rdd1.take(100) res5: Array[Int] = Array(2, 3, 1, 5, 7, 3, 4) scala> rdd1.first res6: Int = 2 |
takeordered倒序排序再取值
scala> rdd1.takeOrdered(3) res7: Array[Int] = Array(1, 2, 3) scala> rdd1.takeOrdered(30) res8: Array[Int] = Array(1, 2, 3, 3, 4, 5, 7) |
生成RDD的两种方式
1.并行化方式生成 (默认分区两个)
手动指定分区
scala> val rdd1 = sc.parallelize(List(1,2,3,5)) rdd1: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[5] at parallelize at <console>:27 scala> rdd1.partitions.length //获取分区数 res9: Int = 2 scala> val rdd1 = sc.parallelize(List(1,2,3,5),3) rdd1: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[6] at parallelize at <console>:27 scala> rdd1.partitions.length res10: Int = 3 |
2.使用textFile读取文件存储系统里的数据
scala> val rdd2 = sc.textFile("hdfs://hadoop01:9000/wordcount/input/a.txt").flatMap(_.split(" ")).map((_,1)).reduceByKey(_+_) rdd2: org.apache.spark.rdd.RDD[(String, Int)] = ShuffledRDD[11] at reduceByKey at <console>:27 scala> rdd2.collect //调用算子得到RDD显示结果 res11: Array[(String, Int)] = Array((hello,6), (beijing,1), (java,1), (gp1808,1), (world,1), (good,1), (qianfeng,1)) scala> val rdd2 = sc.textFile("hdfs://hadoop01:9000/wordcount/input/a.txt",4).flatMap(_.split(" ")).map((_,1)).reduceByKey(_+_) rdd2: org.apache.spark.rdd.RDD[(String, Int)] = ShuffledRDD[26] at reduceByKey at <console>:27 scala> rdd2.partitions.length //也可以自己指定分区数 res15: Int = 4 |