spark從入門到放棄六: RDD 持久化原理
文章地址:http://www.haha174.top/article/details/252484
spark 中一個非常重要的功能特性就是可以將RDD 持久化到記憶體中。當對RDD進行持久化操作時,每個節點都會將自己操作的RDD的partition持久化到記憶體中,並且之後對該RDD的反覆使用直接使用記憶體快取的partion.這樣的話針對一個RDD反覆執行多個操作的場景就只要對RDD計算一次即可。後面直接使用改RDD,而不是需要反覆多次計算該RDD。
巧妙的使用RDD的持久化甚至在某些場景下。可以將spark應用程式的效能提升10倍。對於迭代式演算法和快速互動式應用來說RDD持久話是非常重要的。
要持久化一個RDD。只要呼叫其cache()方法或者persist方法即可。在該RDD第一次被計算出來時,就會直接快取在每一個節點。而且spark持久化機制還是自動容錯的。如果持久化的RDD的任何partion丟失了,那麼soark會自動通過其源RDD使用transformation 操作重新計算該partion。
那麼cache方法和persist方法有什麼區別呢區別在於 cache 是 persist 方法的一種簡化方式。cache()的底層就是呼叫persist的無參版本。同時呼叫persist(MEMORY_ONLY),將資料持久化到記憶體中。如果需要從記憶體中清除快取那麼可以使用unpersist()方法。
spark自己也會在shuffle 操作時,進行資料持久化。比如寫入磁碟,主要是為了在節點失敗時,避免需要重新計算整個過程。
假設我們不適用RDD持久話會出現什麼呢
由圖可知 假設我們需要做兩次count 但是沒有做持久化的話 需要從hdfs 讀取兩次如果資料量比較大的話會非常影響效能。
持久化如下:
cache 和persisit 使用 是有規則的
必須在建立一個RDD 之後執行
另起一行單獨執行這個方法是沒有效果的
例如 list=sc.textFile(“C:\Users\haha174\Desktop\data\test\hive-site.xml”).cache();
但是如果是這樣的
list=sc.textFile(“C:\Users\haha174\Desktop\data\test\hive-site.xml”);
list.cache();
是沒有效果的
下面給出java 示例:
public class Persist {
static SparkConf conf=new SparkConf().setMaster("local").setAppName("persist");
static JavaSparkContext sc=new JavaSparkContext(conf);
public static void main(String[] args){
// noCache();
cache();
}
public static void noCache(){
JavaRDD<String> list=sc.textFile("C:\\Users\\haha174\\Desktop\\data\\test\\hive-site.xml" );
long beginTime=System.currentTimeMillis();
long count=list.count();
System.out.println("無持久化第一次"+(System.currentTimeMillis()-beginTime));
beginTime=System.currentTimeMillis();
count=list.count();
System.out.println("無持久化第二次"+(System.currentTimeMillis()-beginTime));
}
public static void cache(){
JavaRDD<String> list=sc.textFile("C:\\Users\\haha174\\Desktop\\data\\test\\hive-site.xml").cache();
long beginTime=System.currentTimeMillis();
long count=list.count();
System.out.println("持久化第一次"+(System.currentTimeMillis()-beginTime));
beginTime=System.currentTimeMillis();
count=list.count();
System.out.println("持久化第二次"+(System.currentTimeMillis()-beginTime));
}
}
RDD的持久化是可以手動選擇不同的持久化策略的。比如可以將RDD持久化到記憶體中,持久化到磁碟上,使用序列化的方式持久化,多持久化的資料進行多路複用。只要在呼叫persist()時傳入對應的StorageLevel即可。
MEMORY_ONLY:以非序列化的java物件的方式持久化在JVM記憶體中。如果記憶體無法完全儲存RDD所有的partition,那麼那些沒有持久化的partition就會在下一次需要使用它的時候,重新被計算。
MEMORY_AND_DISK
同上但是當某些partiition無法儲存在記憶體中時會持久化到磁碟上,下次需要使用這些partition時,需要從磁碟上讀取。
MEMORY_ONLY_SER
同MEMORY_ONLY 但是會使用java序列化方式。將java 物件序列化後進行持久化可以減少記憶體開銷。但是需要進行反序列化會增大cpu 開銷