【Spark】Spark cache的用法及其誤區分析

Spark cache的用法及其誤區:

一、Cache的用法注意點:
(1)cache之後一定不能立即有其它算子,不能直接去接算子。因爲在實際工作的時候,cache後有算子的話,它每次都會重新觸發這個計算過程。

(2)cache不是一個action,運行它的時候沒有執行一個作業。

(3)cache緩存如何讓它失效:unpersist,它是立即執行的。persist是lazy級別的(沒有計算),unpersist時eager級別的。

cache是persist的一種特殊情況

查看源代碼RDD.scala

/**
 * Set this RDD's storage level topersist its values across operations after the first time
 * it is computed. This can only be usedto assign a new storage level if the RDD does not
 * have a storage level set yet. Localcheckpointing is an exception.
 */
def persist(newLevel: StorageLevel): this.type ={
  if(isLocallyCheckpointed) {
    //This means the user previously called localCheckpoint(), which should havealready
    // marked this RDD for persisting.Here we should override the old storage level with
    // one that is explicitly requestedby the user (after adapting it to use disk).
    persist(LocalRDDCheckpointData.transformStorageLevel(newLevel), allowOverride = true)
  } else {
    persist(newLevel, allowOverride = false)
  }
}

/** Persist this RDD with the default storage level (`MEMORY_ONLY`). */
def persist(): this.type = persist(StorageLevel.MEMORY_ONLY)

/** Persist this RDD with the default storage level (`MEMORY_ONLY`). */
def cache(): this.type = persist()

二、spark常見存儲級別簡單說明:
MEMORY_AND_DISK:spark優先考慮內存,如果內存足夠的話就放在內存中,如果內存不夠用的話,就把數據放在磁盤。

MEMORY_AND_DISK和MEMORY有什麼區別呢?兩個都優先考慮內存,但是MEMORY必須是內存,MEMORY的角度如果內存不夠用的話就出現OOM,或數據會丟失。但是MEMORY_AND_DISK會把數據存在磁盤,不會出現數據丟失,主要會防止OOM,它會極大的降低OOM的可能,但是不管用什麼方式都有可能出現OOM。

MEMORY_ONLY_SER_2,因爲在內存中會有兩個副本,如果其中一份內存崩潰就可以立即切換到另一份副本進行快速的計算,這就極大提升了計算,用空間換時間。

三、通過實例觀察cache:
沒有進行cache時耗時:

17/01/21 14:02:04 INFOscheduler.DAGScheduler: Job 7 finished: count at :28, took4.480135 s

res10: Long = 33254

scala>sc.textFile("/data/5000-8.txt.1").flatMap(.split("")).map(word => (word, 1)).reduceByKey(+_, 1).count

加了一個cache,第一次執行

17/01/21 14:03:48 INFOscheduler.DAGScheduler: Job 9 finished: count at :28, took 4.617932s

res12: Long = 33254

scala>sc.textFile("/data/5000-8.txt.1").flatMap(.split("")).map(word => (word, 1)).reduceByKey(+_, 1).cache.count

第二次執行上面那句話:

17/01/21 14:04:49 INFOscheduler.DAGScheduler: Job 11 finished: count at :28, took 0.462498s

res14: Long = 33254

scala>sc.textFile("/data/5000-8.txt.1").flatMap(.split("")).map(word => (word, 1)).reduceByKey(+_, 1).cache.count

當賦值後再次進行:速度提升了二十倍不止:

val cached =sc.textFile("/data/5000-8.txt.1").flatMap(.split("")).map(word => (word, 1)).reduceByKey(+_, 1).cache

17/01/21 14:08:00 INFOscheduler.DAGScheduler: Job 14 finished: count at :30, took0.079047 s

res17: Long = 33254

scala> cached.count

cache放在內存中只有一份副本,只放在內存中,放在內存的Heap中。不會保存在什麼目錄或者HDFS上,有可能在很多機器的內存,數據量比較小,也有可能在一臺機器的內存中。

四、Persist使用場合
1,某步驟計算特別耗時;

2,計算鏈條特別長;

3,checkpoint所在的RDD也一定要persist(在checkpoint之前,手動進行persist)持久化數據,爲什麼?checkpoint的工作機制,是lazy級別的,在觸發一個作業的時候,開始計算job,job算完之後,轉過來spark的調度框架發現RDD有checkpoint標記,轉過來框架本身又基於這個checkpoint再提交一個作業,checkpoint會觸發一個新的作業,如果不進行持久化,進行checkpoint的時候會重算,如果第一次計算的時候就進行了persist,那麼進行checkpoint的時候速度會非常的快。

4,shuffle之後;

5,shuffle之前(框架默認幫助我們數據持久化到本地磁盤)

persist內存不夠用時數據保存在磁盤的哪裏???

Executor local directory,executor運行的時候,有一個local direcory(本地目錄,這是可以配置的)

cache通過unpersit強制把數據從內存中清除掉,如果計算的時候,肯定會先考慮計算需要的內存,這個時候,cache的數據就與可能丟失。

問題:cache本身不能指定機器做緩存,這個是框架幫你做的;

序列化一般使用kryo序列化器

2份副本不會同時讀數據,實際上只讀一份,另一份是備胎。

如果數據緩存到一臺機器上,如果數據量比較小的話,就放在本地執行計算,如果數據量比較大的話,不幸數據被放在一臺機器上了,它會先排隊,寧願等一會兒,如果不行了,就從其它機器上抓取緩存。一般情況下是不會跨越機器

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章