問題:
1.RDD中基本所有的數(shù)據(jù)都是存儲都在堆內(nèi)存里玉锌,這部分數(shù)據(jù)是通過jvm中的GC管理的啤贩,進行Spark操作的時候可能會出現(xiàn)資源不一致的問題求类,當我們長時間不使用某個變量矫膨,變量會被gc回收狱杰,但是Spark顯示的時候顯示不出來這一部分數(shù)據(jù)瘦材,所以說Spark無法精確的顯示內(nèi)存信息。
2.發(fā)生RDD數(shù)據(jù)丟失的情況的時候仿畸,可以根據(jù)lineage重新計算RDD的數(shù)據(jù)食棕,但是如果依賴關(guān)系是寬依賴,重算的消耗比較大错沽,可以使用checkpoint將數(shù)據(jù)提前寫入磁盤簿晓,讀寫磁盤的過程消耗寶貴的IO資源并且寫入磁盤之后,依賴關(guān)系會消失千埃。
Spark速度非炽径快的原因之一,就是在不同操作中可以在內(nèi)存中持久化或緩存數(shù)據(jù)集放可。當持久化某個RDD后谒臼,每一個節(jié)點都將把計算的分片結(jié)果保存在內(nèi)存中朝刊,并在對此RDD或衍生出的RDD進行的其他動作中重用。這使得后續(xù)的動作變得更加迅速蜈缤。RDD相關(guān)的持久化和緩存拾氓,是Spark最重要的特征之一〗僬粒可以說痪枫,緩存是Spark構(gòu)建迭代式算法和快速交互式查詢的關(guān)鍵。如果一個有持久化數(shù)據(jù)的節(jié)點發(fā)生故障叠艳,Spark 會在需要用到緩存的數(shù)據(jù)時重算丟失的數(shù)據(jù)分區(qū)奶陈。
持久化緩存使用的是堆外內(nèi)存,直接由操作系統(tǒng)管理附较,不受GC的控制吃粒,并且堆外內(nèi)存空間要比堆內(nèi)存空間大3倍。使用起來也比較簡單拒课。當數(shù)據(jù)丟失之后Spark首先會去緩存中查找數(shù)據(jù)徐勃,沒有緩存就檢查checkpoint,如果也沒有就只能重新計算了早像。
val sumed: RDD[(String, Int)] = tuples.reduceByKey(_+_).cache()
需要注意的是cache是transformation函數(shù),所以需要一個action算子來觸發(fā)僻肖。一般來說緩存shuffle之后的數(shù)據(jù),以為shuffle的代價比較大卢鹦,通常shuffle之后緊接一個cache臀脏。
持久化等級:
val NONE = new StorageLevel(false, false, false, false)
val DISK_ONLY = new StorageLevel(true, false, false, false)
val DISK_ONLY_2 = new StorageLevel(true, false, false, false, 2)
val MEMORY_ONLY = new StorageLevel(false, true, false, true)
val MEMORY_ONLY_2 = new StorageLevel(false, true, false, true, 2)
val MEMORY_ONLY_SER = new StorageLevel(false, true, false, false)
val MEMORY_ONLY_SER_2 = new StorageLevel(false, true, false, false, 2)
val MEMORY_AND_DISK = new StorageLevel(true, true, false, true)
val MEMORY_AND_DISK_2 = new StorageLevel(true, true, false, true, 2)
val MEMORY_AND_DISK_SER = new StorageLevel(true, true, false, false)
val MEMORY_AND_DISK_SER_2 = new StorageLevel(true, true, false, false, 2)
val OFF_HEAP = new StorageLevel(false, false, true, false)
參數(shù)(按順序)
useDisk是否使用磁盤
useMemory是否使用內(nèi)存
useoffHeap 是否使用堆外內(nèi)存
deserialized是否使用反序列化
replication 副本的數(shù)量
如果使用cache函數(shù)緩存,默認使用MEMORY_ONLY冀自,如果需要更改持久化等級揉稚,可以使用prisist函數(shù)設(shè)置持久化等級。
緩存的RDD什么時候去釋放呢熬粗?當我們調(diào)用persist緩存一個RDD時搀玖,會調(diào)用registerRDDForCleanup(this),這就是將本身的RDD注冊到一個弱引用中驻呐。當這個RDD變?yōu)椴豢蛇_時灌诅,會自動將該RDD對象插入到referenceQueue中,等到下次GC時就會走doCleanupRDD分支含末。為了讓出內(nèi)存延塑,除了手動unpersist之外,MetadataCleaner的SPARK_CONTEXT會定期清理persistentRdds中過期的數(shù)據(jù)答渔,其實與unpersist產(chǎn)生的作用是一樣的。一旦清理了侥涵,那這個緩存的RDD就沒有強引用了沼撕。