一、簡介
(1)什麼是Spark
Apache Spark 是專爲大規模數據處理而設計的快速通用的計算引擎。Spark擁有Hadoop MapReduce所具有的優點;但不同於MapReduce的是Job中間輸出結果可以保存在內存中,從而不再需要讀寫HDFS,因此Spark能更好地適用於數據挖掘與機器學習等需要迭代的MapReduce的算法。Spark是Scala編寫,方便快速編程。
(2)Spark與MapReduce的區別
都是分佈式計算框架,Spark基於內存,MR基於HDFS。Spark處理數據的能力一般是MR的十倍以上,Spark中除了基於內存計算外,還有DAG有向無環圖來切分任務的執行先後順序
(3)Spark運行模式
- Local: 多用於本地測試,如在eclipse,idea中寫程序測試等。
- Standalone: Standalone是Spark自帶的一個資源調度框架,它支持完全分佈式。
- Yarn: Hadoop生態圈裏面的一個資源調度框架,Spark也是可以基於Yarn來計算的(要基於Yarn來進行資源調度,必須實現AppalicationMaster接口,Spark實現了這個接口,所以可以基於Yarn)。
- Mesos: 資源調度框架。
二、SparkCore
2.1、RDD:彈性分佈式數據集
(1)RDD的五大特性
- RDD是由一系列的partition組成的。
- 函數是作用在每一個partition(split)上的。
- RDD之間有一系列的依賴關係。
- 分區器是作用在K,V格式的RDD上。
- RDD提供一系列最佳的計算位置。
RDD理解圖:
注意:
- textFile方法底層封裝的是讀取MR讀取文件的方式,讀取文件之前先split,默認split大小是一個block大小。
- RDD實際上不存儲數據,這裏方便理解,暫時理解爲存儲數據。
- 什麼是K,V格式的RDD?:如果RDD裏面存儲的數據都是二元組對象,那麼這個RDD我們就叫做K,V格式的RDD。
- 哪裏體現RDD的彈性(容錯)?:partition數量,大小沒有限制,體現了RDD的彈性、RDD之間依賴關係,可以基於上一個RDD重新計算出RDD。
- 哪裏體現RDD的分佈式?:RDD是由Partition組成,partition是分佈在不同節點上的
- RDD提供計算最佳位置,體現了數據本地化。體現了大數據中“計算移動數據不移動”的理念。
2.2、Spark任務執行原理
以上圖中有四個機器節點,Driver和Worker是啓動在節點上的進程,運行在JVM中的進程
- Driver與集羣節點之間有頻繁的通信。
- Driver負責任務(tasks)的分發和結果的回收。任務的調度。如果task的計算結果非常大就不要回收了。會造成oom。
- Worker是Standalone資源調度框架裏面資源管理的從節點。也是JVM進程。
- Master是Standalone資源調度框架裏面資源管理的主節點。也是JVM進程。
2.3、Spark代碼流程
(1)創建SparkConf對象
- 可以設置Application name。
- 可以設置運行模式及資源需求。
(2)創建SparkContext對象
(3)基於Spark的上下文創建一個RDD,對RDD進行處理
(4)應用程序中要有Action類算子來觸發Transformation類算子執行
(5)關閉Spark上下文對象SparkContext
2.4、Transformations轉換算子
(1)概念
Transformations類算子:是一類算子(函數)叫做轉換算子,如map,flatMap,reduceByKey等。Transformations算子是延遲執行,也叫懶加載執行。
(2)Transformation類算子:
- filter: 過濾符合條件的記錄數,true保留,false過濾掉;
- map: 將一個RDD中的每個數據項,通過map中的函數映射變爲一個新的元素(特點:輸入一條,輸出一條數據);
- flatMap: 先map後flat。與map類似,每個輸入項可以映射爲0到多個輸出項;
- sample: 隨機抽樣算子,根據傳進去的小數按比例進行又放回或者無放回的抽樣;
- reduceByKey :將相同的Key根據相應的邏輯進行處理;
- sortByKey/sortBy :作用在K,V格式的RDD上,對key進行升序或者降序排序
2.5、Action行動算子
(1)概念
Action類算子:也是一類算子(函數)叫做行動算子,如foreach,collect,count等。Transformations類算子是延遲執行,Action類算子是觸發執行。一個application應用程序中有幾個Action類算子執行,就有幾個job運行。
(2)Action類算子
- count:返回數據集中的元素數。會在結果計算完成後回收到Driver端。
- take(n):返回一個包含數據集前n個元素的集合。
- first:first=take(1),返回數據集中的第一個元素。
- foreach:循環遍歷數據集中的每個元素,運行相應的邏輯。
- collect:將計算結果回收到Driver端。
2.6、控制算子
(1)概念
控制算子有三種,cache,persist,checkpoint,以上算子都可以將RDD持久化,持久化的單位是partition。cache和persist都是懶執行的,必須有一個action類算子觸發執行。checkpoint算子不僅能將RDD持久化到磁盤,還能切斷RDD之間的依賴關係。
(2)cache介紹
默認將RDD的數據持久化到內存中。cache是懶執行。
注意:chche () = persist()=persist(StorageLevel.Memory_Only)
測試cache文件:文件:見“NASA_access_log_Aug95”文件
測試代碼:
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();
(3)persist介紹
可以指定持久化的級別。最常用的是MEMORY_ONLY和MEMORY_AND_DISK。”_2”表示有副本數。
cache和persist的注意事項:
- cache和persist都是懶執行,必須有一個action類算子觸發執行;
- ache和persist算子的返回值可以賦值給一個變量,在其他job中直接使用這個變量就是使用持久化的數據了。持久化的單位是partition;
- cache和persist算子後不能立即緊跟action算子;
- cache和persist算子持久化的數據當applilcation執行完成之後會被清除;
- 錯誤:rdd.cache().count() 返回的不是持久化的RDD,而是一個數值了。
(4)checkpoint介紹
checkpoint將RDD持久化到磁盤,還可以切斷RDD之間的依賴關係。checkpoint目錄數據當application執行完之後不會被清除。
checkpoint 的執行原理:
- 當RDD的job執行完畢後,會從finalRDD從後往前回溯。
- 當回溯到某一個RDD調用了checkpoint方法,會對當前的RDD做一個標記。
- 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();
2.7、算子補充
transformation:
(1)join,leftOuterJoin,rightOuterJoin,fullOuterJoin
作用在K,V格式的RDD上。根據K進行連接,對(K,V)join(K,W)返回(K,(V,W))
join後的分區數與父RDD分區數多的那一個相同。
(2)union
合併兩個數據集。兩個數據集的類型要一致。
返回新的RDD的分區數是合併RDD分區數的總和。
(3)intersection
取兩個數據集的交集,返回新的RDD與父RDD分區多的一致
(4)subtract
取兩個數據集的差集,結果RDD的分區數與subtract前面的RDD的分區數一致。
(5)mapPartitions
與map類似,遍歷的單位是每個partition上的數據。
(6)distinct(map+reduceByKey+map)
(7)cogroup
當調用類型(K,V)和(K,W)的數據上時,返回一個數據集(K,(Iterable<V>,Iterable<W>)),子RDD的分區與父RDD多的一致。
action:
(1)foreachPartition
遍歷的數據是每個partition的數據。