16.rdd 算子舉例

由於RDD的不可修改的特性,導致RDD的操作與正常面向對象的操作不同,RDD的操作基本分爲3大類:transformation,action,contoller

1.   Transformation

Transformation是通過轉化針對已有的RDD創建出新的RDD

map(func):對調用map的RDD數據集中的每個element都使用func,然後返回一個新的RDD,這個返回的數據集是分佈式的數據集

filter(func): 對調用filter的RDD數據集中的每個元素都使用func,然後返回一個包含使func爲true的元素構成的RDD

flatMap(func):和map差不多,但是flatMap生成的是多個結果

mapPartitions(func):和map很像,但是map是每個element,而mapPartitions是每個partition

mapPartitionsWithSplit(func):和mapPartitions很像,但是func作用的是其中一個split上,所以func中應該有index

sample(withReplacement,faction,seed):抽樣

union(otherDataset):返回一個新的dataset,包含源dataset和給定dataset的元素的集合

distinct([numTasks]):返回一個新的dataset,這個dataset含有的是源dataset中的distinct的element

groupByKey(numTasks):返回(K,Seq[V]),也就是hadoop中reduce函數接受的key-valuelist

reduceByKey(func,[numTasks]):就是用一個給定的reducefunc再作用在groupByKey產生的(K,Seq[V]),比如求和,求平均數

sortByKey([ascending],[numTasks]):按照key來進行排序,是升序還是降序,ascending是boolean類型

join(otherDataset,[numTasks]):當有兩個KV的dataset(K,V)和(K,W),返回的是(K,(V,W))的dataset,numTasks爲併發的任務數

cogroup(otherDataset,[numTasks]):當有兩個KV的dataset(K,V)和(K,W),返回的是(K,Seq[V],Seq[W])的dataset,numTasks爲併發的任務數

 

Transformation特性:

lazy優化:由於Tranformation的lazy特性,也就是創建不馬上運行,對於框架來說,我有足夠的時間查看到儘可能多的步驟,看到的步驟越多,優化的空間就越大。最簡單的優化方式就是步驟合併,例如本來的做法是a=b*3;b=c*3;c=d*3;d=3,步驟合併後就是a=3*3*3*3。

2.   Action

Action操作的目的是得到一個值,或者一個結果

reduce(func):說白了就是聚集,但是傳入的函數是兩個參數輸入返回一個值,這個函數必須是滿足交換律和結合律的

collect():一般在filter或者足夠小的結果的時候,再用collect封裝返回一個數組

count():返回的是dataset中的element的個數

first():返回的是dataset中的第一個元素

take(n):返回前n個elements,這個士driverprogram返回的

takeSample(withReplacement,num,seed):抽樣返回一個dataset中的num個元素,隨機種子seed

saveAsTextFile(path):把dataset寫到一個textfile中,或者hdfs,或者hdfs支持的文件系統中,spark把每條記錄都轉換爲一行記錄,然後寫到file中

saveAsSequenceFile(path):只能用在key-value對上,然後生成SequenceFile寫到本地或者hadoop文件系統

countByKey():返回的是key對應的個數的一個map,作用於一個RDD

foreach(func):對dataset中的每個元素都使用func

3.   Contoller

Contoller動作主要爲持久化RDD,例如cache(),persist(),checkpoint();

具體內容在後續刊物中會講解。

 

 

 

4.   Spark WordCount動手實踐

         本小節通過IDEA具體逐步調試一個WordCount案例,讓學員知道各步驟中RDD的具體類型,併爲下一節逐步解析做鋪墊

(1)     使用的wordCount代碼如下:

  1. object WordCount {
  2.   def main (args: Array[String]) {
  3.     val conf = new SparkConf()//create SparkConf
  4.     conf.setAppName("Wow,My First Spark App")//set app name
  5.     conf.setMaster("local")//run local
  6.     val sc =new SparkContext(conf)
  7.     val lines =sc.textFile("C://Users//feng//IdeaProjects//WordCount//src//SparkText.txt")
  8.     val words = lines.flatMap{ lines => lines.split(" ") }
  9.     val pairs =words.map ( word => (word,1) )
  10.     val reduce = pairs.reduceByKey(_+_)
  11.     val sort_1 = reduce.map(pair=>(pair._2,pair._1))
  12.     val sort_2 = sort_1.sortByKey(false)
  13.     val sort_3=sort_2.map(pair=>(pair._2,pair._1))
  14.     val filter=sort_3.filter(pair=>pair._2>2)
  15.     filter.collect.foreach(wordNumberPair => println(wordNumberPair._1+" : "+wordNumberPair._2))
  16.     sc.stop()
  17.   }
  18. }

(1)       程序使用的SparkText.txt文件內容如下

hadoop hadoop hadoop

spark Flink spark

scala scala object

object spark scala

spark spark

Hadoop hadoop

(2)       程序WordCount調試結果:

通過IDEA的逐步調試,會在調試窗口顯示每一行代碼具體操作什麼類型的RDD,此RDD通過什麼依賴關係依賴於父RDD等重要信息(如圖2-14所示),程序運行結果如圖2-15所示。

 

圖2-14調試過程圖

 

圖2-15wordCount結果

2.8.2 解析RDD生成的內部機制

本小節基於上小節程序的調試結果,逐條查看調試信息內容,並基於信息內容進行講解,並在講解中回顧並複習本章所有內容。

(1)       line = sc.textFile()

本語句的作用在於從外部數據中讀取數據,並生成MapPartitionsRDD。此處需要注意:

如圖2-16所示,可以看出次MapPartitionsRDD的deps(dependency,依賴)爲HadoopRDD,從這裏可以發現其實textFile()過程包含兩個步驟,第一步驟將文件內容轉化爲HadoopRDD(key-value形式,key爲行號),第二步驟將HadoopRDD轉化爲MapPartitionsRDD(value形式,將key-value類型的key刪去)

 

圖2-16通過HadoopRDD獲取數據

(2)       words=line.flatMap()

此命令對於RDD採取transformation(轉換)操作,作用在於將MapPartitionsRDD中的每一個記錄進行以空格爲標記的切分,並把每一個RDD的切分的結果放在一個MapPartitionRDD中

(3)       pairs=words.map(word=>(word,1))

此命令對於RDD採取transformation(轉換)操作,作用在於將MapPartitionsRDD中的每一個記錄(例:spark(value類型))轉換爲key-value類型(例: (spark,1)),便於下一步reduceByKey操作

(4)       reduce = pairs.reduceByKey(_+_)

此命令對於RDD採取action(動作)操作,作用在於通過shuffle將pairs中所有的記錄按照key相同value相加的規則進行處理,並把結果放到一個shuffleRDD中。例((spark,1),(spark,1))變成((spark,2))。

同時需要注意一下兩點:首先本步驟實質上分爲兩個步驟,第一步驟爲local級別的reduce,對當前計算機所擁有的數據先進行reduce操作,生成MapPartitionsRDD;第二步驟爲shuffle級別的reduce,基於第一步驟的結果,對結果進行shuffle-reduce操作,生成最終的shuffleRDD。其次 Action操作進行時,對此操作之前的所有轉換操作進行執行,所以調試過程中會出現此前的除textFile操作的執行時間均非常短,說明RDD轉換操作不直接進行運算。

(5)       sort_1 = reduce.map(pair=>(pair._2,pair._1))

此命令對於RDD採取transformation(轉換)操作,作用在於將shuffleRDD中的每一個記錄的key和value互換,生成一個新的MapPartitionsRDD。例: (spark,2)變爲(2,spark)

(6)       sort_2 = sort_1.sortByKey(false)

此命令對於RDD採取action(動作)操作,作用在於將MapPartitionsRDD根據key進行排序,並生成shuffleRDD

(7)       sort_3=sort_2.map(pair=>(pair._2,pair._1))

此命令對於RDD採取transformation(轉換)操作,作用在於將shuffleRDD中的每一個記錄的key和value互換,生成一個新的MapPartitionsRDD。例: (2,spark)變爲(spark,2)

(8)       filter=sort_3.filter(pair=>pair._2>2)

此命令對於RDD採取transformation(轉換)操作,作用在於根據value值篩選MapPartitionsRDD中的數據,輸出value大於2的記錄

(9)       最後通過collect()方法將結果收集後,使用foreach()方法遍歷數據並通過println()方法打印出所有數據。

 

注:本內容原型來自 IMP 課程筆記

如果技術上有什麼疑問,歡迎加我QQ交流: 1106373297 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章