“夫唯兵者,不祥之器盗冷,物或惡之怠苔,故有道者不處。
君子居則貴左仪糖,用兵則貴右柑司。
兵者不祥之器迫肖,非君子之器,不得已而用之攒驰,恬淡為上蟆湖。
勝而不美,而美之者玻粪,是樂殺人隅津。
夫樂殺人者,則不可得志于天下矣劲室。
吉事尚左伦仍,兇事尚右。
偏將軍居左很洋,上將軍居右充蓝,言以喪禮處之。
殺人之眾蹲缠,以悲哀泣之棺克,戰(zhàn)勝以喪禮處之∠叨ǎ”[1]
Spark對RDD的持久化操作(cache()
娜谊、persist()
、checkpoint()
)是很重要的斤讥,可以將rdd存放在不同的存儲介質中纱皆,方便后續(xù)的操作能重復使用。
cache()
persist()
cache和persist都是用于將一個RDD進行緩存芭商,這樣在之后使用的過程中就不需要重新計算派草,可以大大節(jié)省程序運行時間。
cache和persist的區(qū)別:cache只有一個默認的緩存級別MEMORY_ONLY
铛楣,而persist可以根據(jù)情況設置其它的緩存級別
近迁。
RDD的緩存級別:
查看 StorageLevel 類的源碼
object StorageLevel {
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)
......
}
可以看到這里列出了12種緩存級別,但這些有什么區(qū)別呢簸州?可以看到每個緩存級別后面都跟了一個StorageLevel的構造函數(shù)鉴竭,里面包含了4個或5個參數(shù),如下:
val MEMORY_ONLY = new StorageLevel(false, true, false, true)
查看其構造函數(shù)
class StorageLevel private(
private var _useDisk: Boolean,
private var _useMemory: Boolean,
private var _useOffHeap: Boolean,
private var _deserialized: Boolean,
private var _replication: Int = 1)
extends Externalizable {
......
def useDisk: Boolean = _useDisk
def useMemory: Boolean = _useMemory
def useOffHeap: Boolean = _useOffHeap
def deserialized: Boolean = _deserialized
def replication: Int = _replication
......
}
可以看到StorageLevel類的主構造器包含了5個參數(shù):
- useDisk:使用硬盤(外存)
- useMemory:使用內(nèi)存
- useOffHeap:使用堆外內(nèi)存岸浑,這是Java虛擬機里面的概念搏存,堆外內(nèi)存意味著把內(nèi)存對象分配在Java虛擬機的堆以外的內(nèi)存,這些內(nèi)存直接受操作系統(tǒng)管理(而不是虛擬機)矢洲。這樣做的結果就是能保持一個較小的堆璧眠,以減少垃圾收集對應用的影響。
- deserialized:反序列化,其逆過程序列化(Serialization)是java提供的一種機制责静,將對象表示成一連串的字節(jié)袁滥;而反序列化就表示將字節(jié)恢復為對象的過程。序列化是對象永久化的一種機制泰演,可以將對象及其屬性保存起來呻拌,并能在反序列化后直接恢復這個對象
- replication:備份數(shù)(在多個節(jié)點上備份)
理解了這5個參數(shù),StorageLevel 的12種緩存級別就不難理解了睦焕。
val MEMORY_AND_DISK_SER_2 = new StorageLevel(true, true, false, false, 2) 就表示使用這種緩存級別的RDD將存儲在硬盤
以及內(nèi)存
中藐握,使用序列化
(在硬盤中),并且在多個節(jié)點上備份2
份(正常的RDD只有一份)
checkpoint()
sc.sparkContext.setCheckpointDir('...')
......
......
rdd.cache()
rdd.checkpoint()
......
checkpoint接口是將RDD持久化到HDFS中垃喊,與persist的區(qū)別是checkpoint會切斷此RDD之前的依賴關系猾普,而persist會保留依賴關系。checkpoint的兩大作用:一是spark程序長期駐留本谜,過長的依賴會占用很多的系統(tǒng)資源初家,定期checkpoint可以有效的節(jié)省資源;二是維護過長的依賴關系可能會出現(xiàn)問題乌助,一旦spark程序運行失敗溜在,RDD的容錯成本會很高。
注意:checkpoint執(zhí)行前要先進行cache他托,避免兩次計算掖肋。
-
老子《道德經(jīng)》第三十一章,老子故里赏参,中國鹿邑志笼。 ?