1. 產生來源
- 閱讀以下代碼
val lines = sc.textFile("hdfs://...")
lines.filter(_.contain("my")).count //第一個job
lines.filter(_.contain("my1")).count //第二個job
- 分析代碼
上面的代碼當執行到第一個job的時候觸發一個job,當執行時會去hdfs中下載文件並執行; 當第二次count時又觸發了一個job又需要去hdfs讀取文件, 合理?
2. cache
- 此處如果使用了cache算子,那麼在執行第二個count的時候數據可以直接從緩存中獲取
- 實際上cache底層也是使用的persist算子
def cacheDemo(hdfsUrl:String, sc:SparkContext): Unit = {
var lines: RDD[String] = sc.textFile(hdfsUrl)
lines = lines.cache()
val s1 = System.currentTimeMillis()
lines.count()
val e1 = System.currentTimeMillis()
lines.count()
val e2 = System.currentTimeMillis()
println("first count " + (e1 - s1))
println("first count " + (e2 - e1))
}
3. persist
- persist他可以指定使用哪一個級別的緩存, 所有的緩存級別在StorageLevel中的有
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-MtFtHH6M-1586398176300)(en-resource://database/1415:1)]
- 使用案列
var lines: RDD[String] = sc.textFile(hdfsUrl)
lines = lines.persist(StorageLevel.MEMORY_AND_DISK)
val s1 = System.currentTimeMillis()
lines.count()
val e1 = System.currentTimeMillis()
lines.count()
val e2 = System.currentTimeMillis()
println("first count " + (e1 - s1))
println("first count " + (e2 - e1))
4. cache & persist
- 他們都是懶執行的, 並且持久化最小單元爲爲partition
- 調用方法後需要賦值給一個RDD, 之後直接使用生成的這個RDD
- 緩存的數據在Application執行完成之後自動清除
5. checkpoint
-
作用: 將數據直接持久化到指定目錄,當lineage計算非常複雜,可以嘗試使用checkpoint;checkpoint還可以切斷RDD的依賴關係
-
注意: checkpoint的做法是先把job執行完, 然後回溯到第一個RDD一個一個的檢查是否做了checkpoint然後重新計算緩存;爲了解決這個問題可以對需要checkpoin 的RDD先進行cache
val lines: RDD[String] = sc.textFile(hdfsUrl)
sc.setCheckpointDir("/directory")
lines.checkpoint()
val s1 = System.currentTimeMillis()
lines.count()
val e1 = System.currentTimeMillis()
lines.count()
val e2 = System.currentTimeMillis()
println("first count " + (e1 - s1))
println("first count " + (e2 - e1))