RDD是Spark計算的時候操作的數據集,全稱是Resilient Distributed Datasets(彈性分佈式數據集)。
數據是分佈在多臺機器上的,爲了好處理,將這些分佈的數據抽象成一個RDD。這個RDD就是所有數據的代理,操作RDD就相當於操作分佈在每臺機器上的數據。
而RDD又是由很多分區組成的,操作RDD的時候,對RDD裏面的每一個分區進行操作。而這些操作真正的會分發到每臺機器上,並且擁有容錯機制。一個分區針對一臺機器,如果那個機器上的數據過大了,就對對應多個分區。
對RDD的操作分爲兩種transformation和action:
transformation可以將一個RDD轉換爲下一個RDD,也是爲了方便下一步操作。
action是可以觸發任務的,當RDD達到一定的條件以後就可以調用action任務,開始真正的處理。
一下操作就是先將文件transformtion成一個RDD,然後action,這個collect是一個action的算式。將分佈在不同機器上的數據通過網絡收集過來,並且顯示。
//執行該句只是告訴後續的程序,到該路徑下讀取數據
scala> val rdd1 = sc.textFile("hdfs://slave1.hadoop:9000/spark")
rdd1: org.apache.spark.rdd.RDD[String] = hdfs://slave1.hadoop:9000/spark MapPartitionsRDD[31] at textFile at <console>:24
//action操作,將數據收集過來
scala> rdd1.collect
res8: Array[String] = Array(hello jim, hello wo, hello ni, hello jarry)
//transformaation操作
scala> val rdd2 = rdd1.map(_.split(" "))
rdd2: org.apache.spark.rdd.RDD[Array[String]] = MapPartitionsRDD[32] at map at <console>:26
//transformation操作
scala> val rdd3 = rdd1.flatMap(_.split(" "))
rdd3: org.apache.spark.rdd.RDD[String] = MapPartitionsRDD[33] at flatMap at <console>:26
//action操作
scala> val reduce = wordAndOne.reduceByKey(_+_).sortBy(_._2,false).saveAsTextFile("hdfs://slave1.hadoop:9000/spark/output")
reduce: Unit = ()
transformation是lazy的,延遲執行,transformtion後的數據只有遇到action的時候才提交到集羣上真正的運行。
如何證明transformation是lazy的呢,首先讓我們讀取hdfs下一個不存在的文件
scala> val rdd4 = sc.textFile("/sp")
rdd4: org.apache.spark.rdd.RDD[String] = /sp MapPartitionsRDD[100] at textFile at <console>:24
哎,發現時可以的,但這個文件是不存在的,爲什麼會讀到呢。因爲它就沒有真正的去讀取,只有執行的action的操作,纔會去執行,此時就會報錯了。說是文件不存在,所以說transformation是lazy的。
scala> val rdd4 = sc.textFile("/sp").collect
org.apache.hadoop.mapred.InvalidInputException: Input path does not exist: hdfs://ns/sp
at org.apache.hadoop.mapred.FileInputFormat.singleThreadedListStatus(FileInputFormat.java:287)
at org.apache.hadoop.mapred.FileInputFormat.listStatus(FileInputFormat.java:229)
at org.apache.hadoop.mapred.FileInputFormat.getSplits(FileInputFormat.java:315)
at org.apache.spark.rdd.HadoopRDD.getPartitions(HadoopRDD.scala:194)
at org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:252)
at org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:250)
at scala.Option.getOrElse(Option.scala:121)
at org.apache.spark.rdd.RDD.partitions(RDD.scala:250)
at org.apache.spark.rdd.MapPartitionsRDD.getPartitions(MapPartitionsRDD.scala:35)
at org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:252)
at org.apache.spark.rdd.RDD$$anonfun$partitions$2.apply(RDD.scala:250)
at scala.Option.getOrElse(Option.scala:121)
at org.apache.spark.rdd.RDD.partitions(RDD.scala:250)
at org.apache.spark.SparkContext.runJob(SparkContext.scala:2087)
at org.apache.spark.rdd.RDD$$anonfun$collect$1.apply(RDD.scala:936)
at org.apache.spark.rdd.RDDOperationScope$.withScope(RDDOperationScope.scala:151)
at org.apache.spark.rdd.RDDOperationScope$.withScope(RDDOperationScope.scala:112)
at org.apache.spark.rdd.RDD.withScope(RDD.scala:362)
at org.apache.spark.rdd.RDD.collect(RDD.scala:935)
... 48 elided
scala>