目錄標題
什麼是RDD
當有多臺電腦,多臺電腦上的分佈着不同的數據,我們使用RDD來統一這些數據命名,故而RDD就是分佈式數據集.
當有了整個在多臺計算機分佈的大型數組RDD,我們纔可以通過一系列算子對其進行操作
RDD分區以及Shuffle操作
- RDD分區是一個並行計算實現的手段
1.查看分區的手段
(1)使用partitions查看
rdd.partitions.size
(2)使用webUI頁面查看
node01:4040
2.通過算子指定分區數
一般情況下涉及Shuffle的操作的算子都可以指定分區數,在最後一位參數指定分區數,如果沒有指定默認從父RDD中繼承分區數
3.Spark 中的 Shuffle 操作的特點
- 只有 Key-Value 型的 RDD 纔會有 Shuffle 操作, 例如 RDD[(K, V)], 但是有一個特例, 就是 repartition 算子可以對任何數據類型 Shuffle
RDD的緩存
1.RDD緩存作用
緩存能夠幫助開發者在進行一些昂貴操作後, 將其結果保存下來, 以便下次使用無需再次執行, 緩存能夠顯著的提升性能.
2.RDD緩存API
轉換算子的作用:生成RDD,以及RDD之間的依賴關係
Action算子的作用:生成job,去執行job,有一個job,RDD就要執行一次
我們使用緩存的意義就是減少shuffle,緩存其他算子生成的結果
(1)cahe緩存
可以使用 cache 方法進行緩存
val conf = new SparkConf().setMaster("local[6]").setAppName("debug_string")
val sc = new SparkContext(conf)
val interimRDD = sc.textFile("dataset/access_log_sample.txt")
.map(item => (item.split(" ")(0), 1))
.filter(item => StringUtils.isNotBlank(item._1))
.reduceByKey((curr, agg) => curr + agg)
.cache() //緩存rdd
val resultLess = interimRDD.sortBy(item => item._2, ascending = true).first()
val resultMore = interimRDD.sortBy(item => item._2, ascending = false).first()
println(s"出現次數最少的 IP : $resultLess, 出現次數最多的 IP : $resultMore")
sc.stop()
(2)persist(可以指定緩存級別的緩存)
al conf = new SparkConf().setMaster("local[6]").setAppName("debug_string")
val sc = new SparkContext(conf)
val interimRDD = sc.textFile("dataset/access_log_sample.txt")
.map(item => (item.split(" ")(0), 1))
.filter(item => StringUtils.isNotBlank(item._1))
.reduceByKey((curr, agg) => curr + agg)
.persist(StorageLevel.MEMORY_ONLY)
val resultLess = interimRDD.sortBy(item => item._2, ascending = true).first()
val resultMore = interimRDD.sortBy(item => item._2, ascending = false).first()
println(s"出現次數最少的 IP : $resultLess, 出現次數最多的 IP : $resultMore")
sc.stop()
persist() 是 persist(newLevel: StorageLevel) 的一個別名, persist(newLevel: StorageLevel) 能夠指定緩存的級別
3.緩存級別設置
是否使用磁盤緩存?
是否使用內存緩存?
是否使用堆外內存?
緩存前是否先序列化?
是否需要有副本?
在這裏插入代碼片
是否反序列化形式存儲,如果是false是二進制數據,如果是true存的是對象
4.緩存級別選擇
- Spark 的存儲級別的選擇,核心問題是在 memory 內存使用率和 CPU 效率之間進行權衡。建議按下面的過程進行存儲級別的選擇:
- 一般使用RDD 默認存儲級別MEMORY_ONLY。這是 CPU 效率最高的選項,因爲沒有序列化這個過程,允許 RDD 上的操作儘可能快地運行.
- MEMORY_ONLY_SER 他使用了序列化 數據變爲二進制保存更加節省空間,但仍然能夠快速訪問。(Java和Scala)
- 不要溢出到磁盤,除非計算您的數據集的函數是昂貴的.溢寫效率比較低
- 如果需要快速故障恢復,請使用複製的存儲級別(末尾加2)。複製的數據可讓您你繼續在 RDD 上運行任務,而無需等待重新計算一個丟失的分區.
RDD的Checkpoint
1.Checkpoint使用場景
就是可以將迭代多次RDD存儲在HDFS上
Checkpoint 的主要作用是斬斷 RDD 的依賴鏈, 並且將數據存儲在可靠的存儲引擎中, 例如支持分佈式存儲和副本機制的 HDFS.
2.Checkpoint 和 Cache 的區別
他們的區別主要在以下兩點
- Checkpoint 可以保存數據到 HDFS 這類可靠的存儲上, Persist 和 Cache 只能保存在本地的磁盤和內存中
- Checkpoint 可以斬斷 RDD 的依賴鏈, 而 Persist 和 Cache 不行
- 因爲 CheckpointRDD 沒有向上的依賴鏈, 所以程序結束後依然存在, 不會被刪除. 而 Cache 和 Persist 會在程序結束後立刻被清除.
3.使用 Checkpoint
val conf = new SparkConf().setMaster("local[6]").setAppName("debug_string")
val sc = new SparkContext(conf)
//設置保存Checkpoint目錄,也可以設置hdfs上目錄
sc.setCheckpointDir("checkpoint")
val interimRDD = sc.textFile("dataset/access_log_sample.txt")
.map(item => (item.split(" ")(0), 1))
.filter(item => StringUtils.isNotBlank(item._1))
.reduceByKey((curr, agg) => curr + agg)
interimRDD.checkpoint() //
interimRDD.collect().foreach(println(_))
sc.stop()
在使用 Checkpoint 之前需要先設置 Checkpoint 的存儲路徑, 而且如果任務在集羣中運行的話, 這個路徑必須是 HDFS 上的路徑
開啓 Checkpoint
val interimRDD = sc.textFile("dataset/access_log_sample.txt")
.map(item => (item.split(" ")(0), 1))
.filter(item => StringUtils.isNotBlank(item._1))
.reduceByKey((curr, agg) => curr + agg)
.cache() //在Checkpoint之前先cache緩存一下
interimRDD.checkpoint()
interimRDD.collect().foreach(println(_))
checkpoint 之前先 cache 一下, 因爲 checkpoint 會重新計算整個 RDD 的數據然後再存入 HDFS 等地方.
所以上述代碼中如果 checkpoint 之前沒有 cache, 則整個流程會被計算兩次, 一次是 checkpoint, 另外一次是 collect