Spark初始
什麼是Spark
- Apache Spark
Apache Spark 是專爲大規模數據處理而設計的快速通用的計算引擎。Spark是UC Berkeley AMP lab (加州大學伯克利分校的AMP實驗室)所開源的類Hadoop MapReduce的通用並行計算框架,Spark擁有Hadoop MapReduce所具有的優點;但不同於MapReduce的是Job中間輸出結果可以保存在內存中,從而不再需要讀寫HDFS,因此Spark能更好地適用於數據挖掘與機器學習等需要迭代的MapReduce的算法。
Spark是Scala編寫,方便快速編程。
總體技術棧講解
Spark與MapReduce的區別
- 區別
都是分佈式計算框架,Spark基於內存,MR基於HDFS。Spark處理數據的能力一般是MR的十倍以上,Spark中除了基於內存計算外,還有DAG有向無環圖來切分任務的執行先後順序。
Spark運行模式
- Local
多用於本地測試,如在eclipse,idea中寫程序測試等。 - Standalone
Standalone是Spark自帶的一個資源調度框架,它支持完全分佈式。 - Yarn
Hadoop生態圈裏面的一個資源調度框架,Spark也是可以基於Yarn來計算的。 - Mesos
資源調度框架。
要基於Yarn來進行資源調度,必須實現AppalicationMaster接口,Spark實現了這個接口,所以可以基於Yarn。
SparkCore
RDD
- 概念:RDD(Resilient Distributed Dateset),彈性分佈式數據集。
- RDD的五大特性:
1.RDD是由一系列的partition組成的。
2.函數是作用在每一個partition(split)上的。
3.RDD之間有一系列的依賴關係。
4.分區器是作用在K,V格式的RDD上。
5.RDD提供一系列最佳的計算位置。 - RDD理解圖:
- 注意:
1.textFile方法底層封裝的是讀取MR讀取文件的方式,讀取文件之前先split,默認split大小是一個block大小。
2.RDD實際上不存儲數據,這裏方便理解,暫時理解爲存儲數據。
3.什麼是K,V格式的RDD?
如果RDD裏面存儲的數據都是二元組對象,那麼這個RDD我們就叫做K,V格式的RDD。
4.哪裏體現RDD的彈性(容錯)?
partition數量,大小沒有限制,體現了RDD的彈性。
RDD之間依賴關係,可以基於上一個RDD重新計算出RDD。
5.哪裏體現RDD的分佈式?
RDD是由Partition組成,partition是分佈在不同節點上的。
6.RDD提供計算最佳位置,體現了數據本地化。體現了大數據中“計算移動數據不移動”的理念。
Spark任務執行原理
以上圖中有四個機器節點,Driver和Worker是啓動在節點上的進程,運行在JVM中的進程。
- Driver與集羣節點之間有頻繁的通信。
- Driver負責任務(tasks)的分發和結果的回收。任務的調度。如果task的計算結果非常大就不要回收了。會造成oom。
- Worker是Standalone資源調度框架裏面資源管理的從節點。也是JVM進程。
- Master是Standalone資源調度框架裏面資源管理的主節點。也是JVM進程。
Spark代碼流程
- 創建SparkConf對象
可以設置Application name。可以設置運行模式及資源需求。 - 創建SparkContext對象
- 基於Spark的上下文創建一個RDD,對RDD進行處理。
- 應用程序中要有Action類算子來觸發Transformation類算子執行。
- 關閉Spark上下文對象SparkContext。
Transformations轉換算子
- 概念:Transformations類算子是一類算子(函數)叫做轉換算子,如map,flatMap,reduceByKey等。Transformations算子是延遲執行,也叫懶加載執行。
- Transformation類算子:
1.filter:過濾符合條件的記錄數,true保留,false過濾掉。
2.map:將一個RDD中的每個數據項,通過map中的函數映射變爲一個新的元素。
特點:輸入一條,輸出一條數據。
3.flatMap:先map後flat。與map類似,每個輸入項可以映射爲0到多個輸出項。
4.sample:隨機抽樣算子,根據傳進去的小數按比例進行又放回或者無放回的抽樣。
reduceByKey:將相同的Key根據相應的邏輯進行處理。
sortByKey/sortBy:作用在K,V格式的RDD上,對key進行升序或者降序排序。
Action行動算子
- 概念:Action類算子也是一類算子(函數)叫做行動算子,如foreach,collect,count等。Transformations類算子是延遲執行,Action類算子是觸發執行。一個application應用程序中有幾個Action類算子執行,就有幾個job運行。
- Action類算子:
1.count:返回數據集中的元素數。會在結果計算完成後回收到Driver端。
2.take(n):返回一個包含數據集前n個元素的集合。
3.first:first=take(1),返回數據集中的第一個元素。
4.foreach:循環遍歷數據集中的每個元素,運行相應的邏輯。
5.collect:將計算結果回收到Driver端。
思考:一千萬條數據量的文件,過濾掉出現次數多的記錄,並且其餘記錄按照出現次數降序排序。
控制算子
- 概念:控制算子有三種,cache,persist,checkpoint,以上算子都可以將RDD持久化,持久化的單位是partition。cache和persist都是懶執行的。必須有一個action類算子觸發執行。checkpoint算子不僅能將RDD持久化到磁盤,還能切斷RDD之間的依賴關係。
- cache
默認將RDD的數據持久化到內存中。cache是懶執行。
注意:chche () =persist()=persist(StorageLevel.Memory_Only)
SparkConf conf = new SparkConf();
conf.setMaster("local").setAppName("CacheTest");
JavaSparkContext jsc = new JavaSparkContext(conf);
JavaRDD<String> lines = jsc.textFile("./NASA_access_log_Aug95");
lines = lines.cache();
long startTime = System.currentTimeMillis();
long count = lines.count();
long endTime = System.currentTimeMillis();
System.out.println("共"+count+ "條數據,"+"初始化時間+cache時間+計算時間="+
(endTime-startTime));
long countStartTime = System.currentTimeMillis();
long countrResult = lines.count();
long countEndTime = System.currentTimeMillis();
System.out.println("共"+countrResult+ "條數據,"+"計算時間="+ (countEndTime-
countStartTime));
jsc.stop();
- persist:可以指定持久化的級別。最常用的是MEMORY_ONLY和MEMORY_AND_DISK。”_2”表示有副本數。
- cache和persist的注意事項:
1.cache和persist都是懶執行,必須有一個action類算子觸發執行。
2.cache和persist算子的返回值可以賦值給一個變量,在其他job中直接使用這個變量就是使用持久化的數據了。持久化的單位是partition。
3.cache和persist算子後不能立即緊跟action算子。
4.cache和persist算子持久化的數據當applilcation執行完成之後會被清除。
錯誤:rdd.cache().count() 返回的不是持久化的RDD,而是一個數值了。 - checkpoint
checkpoint將RDD持久化到磁盤,還可以切斷RDD之間的依賴關係。checkpoint目錄數據當application執行完之後不會被清除。
checkpoint 的執行原理:
1.當RDD的job執行完畢後,會從finalRDD從後往前回溯。
2.當回溯到某一個RDD調用了checkpoint方法,會對當前的RDD做一個標記。
3.Spark框架會自動啓動一個新的job,重新計算這個RDD的數據,將數據持久化到HDFS上。
優化:對RDD執行checkpoint之前,最好對這個RDD先執行cache,這樣新啓動的job只需要將內存中的數據拷貝到HDFS上就可以,省去了重新計算這一步。
使用:
SparkConf conf = new SparkConf();
conf.setMaster("local").setAppName("checkpoint");
JavaSparkContext sc = new JavaSparkContext(conf);
sc.setCheckpointDir("./checkpoint");
JavaRDD<Integer> parallelize = sc.parallelize(Arrays.asList(1,2,3));
parallelize.checkpoint();
parallelize.count();
sc.stop();