Spark核心程式設計之RDD持久化詳解
RDD持久化原理
Spark非常重要的一個功能特性就是可以將RDD持久化在記憶體中。當對RDD執行持久化操作時,每個節點都會將自己操作的RDD的partition持久化到記憶體中,並且在之後對該RDD的反覆使用中,直接使用記憶體快取的partition。這樣的話,對於針對一個RDD反覆執行多個操作的場景,就只要對RDD計算一次即可,後面直接使用該RDD,而不需要反覆計算多次該RDD。
巧妙使用RDD持久化,甚至在某些場景下,可以將spark應用程式的效能提升10倍。對於迭代式演算法和快速互動式應用來說,RDD持久化,是非常重要的。
要持久化一個RDD,只要呼叫其cache()或者persist()方法即可。在該RDD第一次被計算出來時,就會直接快取在每個節點中。而且Spark的持久化機制還是自動容錯的,如果持久化的RDD的任何partition丟失了,那麼Spark會自動通過其源RDD,使用transformation操作重新計算該partition。
cache()和persist()的區別在於,cache()是persist()的一種簡化方式,cache()的底層就是呼叫的persist()的無參版本,同時就是呼叫persist(MEMORY_ONLY),將資料持久化到記憶體中。如果需要從記憶體中清楚快取,那麼可以使用unpersist()方法。
Spark自己也會在shuffle操作時,進行資料的持久化,比如寫入磁碟,主要是為了在節點失敗時,避免需要重新計算整個過程。
圖解持久化和不持久化
不使用RDD持久化的問題的原理
RDD持久化的工作原理
RDD持久化實戰
package cn.spark.study .core;
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
/**
* RDD持久化
* @author Administrator
*
*/
public class Persist {
public static void main(String[] args) {
SparkConf conf = new SparkConf()
.setAppName ("Persist")
.setMaster("local");
JavaSparkContext sc = new JavaSparkContext(conf);
// cache()或者persist()的使用,是有規則的
// 必須在transformation或者textFile等建立了一個RDD之後,直接連續呼叫cache()或persist()才可以
// 如果你先建立一個RDD,然後單獨另起一行執行cache()或persist()方法,是沒有用的
// 而且,會報錯,大量的檔案會丟失
JavaRDD<String> lines = sc.textFile("C://Users//Administrator//Desktop//spark.txt")
.cache();
long beginTime = System.currentTimeMillis();
long count = lines.count();
System.out.println(count);
long endTime = System.currentTimeMillis();
System.out.println("cost " + (endTime - beginTime) + " milliseconds.");
beginTime = System.currentTimeMillis();
count = lines.count();
System.out.println(count);
endTime = System.currentTimeMillis();
System.out.println("cost " + (endTime - beginTime) + " milliseconds.");
sc.close();
}
}
RDD持久化策略
RDD持久化是可以手動選擇不同的策略的。比如可以將RDD持久化在記憶體中、持久化到磁碟上、使用序列化的方式持久化,多持久化的資料進行多路複用。只要在呼叫persist()時傳入對應的StorageLevel即可。
如何選擇RDD持久化策略?
Spark提供的多種持久化級別,主要是為了在CPU和記憶體消耗之間進行取捨。下面是一些通用的持久化級別的選擇建議:
1、優先使用MEMORY_ONLY,如果可以快取所有資料的話,那麼就使用這種策略。因為純記憶體速度最快,而且沒有序列化,不需要消耗CPU進行反序列化操作。
2、如果MEMORY_ONLY策略,無法儲存的下所有資料的話,那麼使用MEMORY_ONLY_SER,將資料進行序列化進行儲存,純記憶體操作還是非常快,只是要消耗CPU進行反序列化。
3、如果需要進行快速的失敗恢復,那麼就選擇帶字尾為_2的策略,進行資料的備份,這樣在失敗時,就不需要重新計算了。
4、能不使用DISK相關的策略,就不用使用,有的時候,從磁碟讀取資料,還不如重新計算一次。