一些概念之二

weixin_34194087發表於2018-11-04

【Spark簡介】

Apache Spark是一個圍繞速度、易用性和複雜分析構建的大資料處理框架。最初在2009年由加州大學伯克利分校的AMPLab開發,並於2010年成為Apache的開源專案之一。Spark作為Apache頂級的開源專案,是一個快速、通用的大規模資料處理引擎,和Hadoop的MapReduce計算框架類似,但是相對於MapReduce,Spark憑藉其可伸縮、基於記憶體計算等特點,以及可以直接讀寫Hadoop上任何格式資料的優勢,進行批處理時更加高效,並有更低的延遲。Spark已經成為輕量級大資料快速處理的統一平臺,各種不同的應用,如實時流處理、機器學習、互動式查詢等,都可以通過Spark建立在不同的儲存和執行系統上。相對於MapReduce上的批量計算、迭代型計算以及基於Hive的SQL查詢,Spark可以帶來上百倍的效能提升。

【Spark生態系統元件】

Spark Core:整個生態系統的核心元件,是一個分散式大資料處理框架。Spark Core提供了多種資源排程管理,通過記憶體計算、有向無環圖(DAG)等機制保證分散式計算的快速,並引入了RDD的抽象保證資料的高容錯性。
Spark Streaming:基於微批量方式的計算和處理,可以用於對實時資料流進行高吞吐、高容錯的流式處理。
Spark SQL:通過JDBC API將Spark資料集暴露出去,而且還可以用傳統的BI和視覺化工具在Spark資料上執行類似SQL的查詢。使用者還可以用Spark SQL對不同格式的資料執行ETL,將其轉化暴露給特定的查詢。
Spark MLlib:一個可擴充套件的Spark機器學習庫,由通用的學習演算法和工具組成。打通資料收集、資料清理、特徵提取,模型訓練,測試、評估整個流程。
Spark GraphX:用於圖計算和並行圖計算的API。通過引入彈性分散式屬性圖,一種頂點和邊都帶有屬性的有向多重圖,擴充套件了Spark RDD。

【Spark應用場景】

1、快速查詢系統:基於日誌資料的快速查詢系統業務構建於Spark之上,利用其快速查詢以及記憶體表等優勢,能夠承擔大部分日誌資料的即時查詢工作;在效能方面,普遍比Hive快2~10倍,如果使用記憶體表的功能,效能將會比Hive快百倍。
2、實時日誌採集處理:通過Spark Streaming實時進行業務日誌採集,快速迭代處理,並進行綜合分析,能夠滿足線上系統分析要求。
3、業務推薦系統:使用Spark將業務推薦系統的小時和天級別的模型訓練轉變為分鐘級別的模型訓練,有效優化相關排名、個性化推薦以及熱點點選分析等。
4、定製廣告系統:在定製廣告業務方面需要大資料做應用分析、效果分析、定向優化等,藉助Spark快速迭代的優勢,實現了“資料實時採集、演算法實時訓練、系統實時預測”的流程,支援上億的請求量處理;模擬廣告投放計算效率高、延遲小,同MapReduce相比延遲至少降低一個數量級。

【Spark四大特性】

1、速度快:與Hadoop的MapReduce相比,Spark基於記憶體的運算要快100倍以上;而基於磁碟的運算也要快10倍以上。Spark實現了高效的DAG執行引擎,可以通過基於記憶體來高效地處理資料流。
2、易使用:支援Java、Python和Scala的API,還支援超過80種高階演算法,使使用者可以快速構建不同應用。
3、通用性:Spark提供了統一的解決方案。Spark可以用於批處理、互動式查詢(Spark SQL)、實時流處理(Spark Streaming)、機器學習(通過Spark MLlib)和圖計算(Spark GraphX)。
這些不同型別的處理都可以在同一應用中無縫使用。Spark統一的解決方案非常具有吸引力,畢竟任何公司都想用統一的平臺處理問題,減少開發和維護的人力成本和部署平臺的物理成本。
4、相容性:Spark可以非常方便地與其他開源產品進行融合。比如,可以使用Hadoop的YARN作為它的資源管理和排程器,並且可以處理所有Hadoop支援的資料,包括HDFS、HBase等。這對於已部署Hadoop叢集的使用者特別重要,因為不需要做任何資料遷移就可以使用Spark強大的處理能力。Spark也可以不依賴第三方的資源管理器和排程器,它實現了Standalone作為其內建資源管理器和排程框架。

【Spark基本架構】

Cluster Manager:Spark的叢集管理器,主要負責資源的分配與管理。叢集管理器分配的資源屬於一級分配,它將各個Worker上的記憶體、CPU等資源分配給應用程式,但是並不負責對Executor的資源分配。目前,Standalone、YARN、Mesos、EC2等都可以作為Spark的叢集管理器。
Worker:Spark的工作節點。對Spark應用程式來說,由叢集管理器分配得到資源的Worker節點主要負責以下工作:建立Executor,將資源和任務進一步分配給Executor,同步資源資訊給Cluster Manager。
Executor:執行計算任務的一線程式。主要負責任務的執行以及與Worker、Driver App的資訊同步。
Driver App:客戶端驅動程式,也可以理解為客戶端應用程式,用於將任務程式轉換為RDD和DAG,並與Cluster Manager進行通訊與排程。

【Spark三種部署方式】

1、Standalone模式:Spark框架自帶了完整的資源排程管理服務,可以獨立部署到一個叢集中,而不需要依賴其他系統來為其提供資源管理排程服務。在架構的設計上,Spark與MapReduce1.0完全一致,都是由一個Master和若干個Slave構成,並且以槽(slot)作為資源分配單位。不同的是,Spark中的槽不再像MapReduce1.0那樣分為Map槽和Reduce槽,而是隻設計了統一的一種槽提供給各種任務來使用。
2、Spark on Mesos模式:Mesos是一種資源排程管理框架,可以為執行在它上面的Spark提供服務。Spark on Mesos模式中,Spark程式所需要的各種資源,都由Mesos負責排程。
3、Spark on YARN模式:Spark可執行於YARN之上,與Hadoop進行統一部署,即“Spark on YARN”,依賴於YARN的資源管理和排程依賴,分散式儲存則依賴HDFS。

【Spark一些基本概念】

RDD:Resillient Distributed Dataset(彈性分散式資料集)的簡稱,是分散式記憶體的一個抽象概念,提供了一種高度受限的共享記憶體模型。
DAG:是Directed Acyclic Graph(有向無環圖)的簡稱,反映RDD之間的依賴關係。
Executor:是執行在工作節點(WorkerNode)的一個程式,負責執行Task。
Application:使用者編寫的Spark應用程式。
Task:執行在Executor上的工作單元。
Job:一個Job包含多個RDD及作用於相應RDD上的各種操作。
Stage:是Job的基本排程單位,一個Job會分為多組Task,每組Task被稱為Stage,或者也被稱為TaskSet,代表了一組關聯的、相互之間沒有Shuffle依賴關係的任務組成的任務集。

【Spark RDD設計背景】

許多迭代式演算法(比如機器學習、圖演算法等)和互動式資料探勘工具,共同之處是,不同計算階段之間會重用中間結果。目前的MapReduce框架都是把中間結果寫入到HDFS中,帶來了大量的資料複製、磁碟IO和序列化開銷。RDD就是為了滿足這種需求而出現的,它提供了一個抽象的資料架構,不必關心底層資料的分散式特性,只需將具體的應用邏輯表達為一系列轉換處理,不同RDD之間的轉換操作形成依賴關係,可以實現管道化,避免中間資料儲存。一個RDD就是一個分散式物件集合,本質上是一個只讀的分割槽記錄集合,每個RDD可分成多個分割槽,每個分割槽就是一個資料集片段,並且一個RDD的不同分割槽可以被儲存到叢集中不同的節點上,從而可以在叢集中的不同節點上進行平行計算。

【Spark RDD基本概念】

RDD是一種高度受限的共享記憶體模型,即RDD是隻讀的記錄分割槽的集合,不能直接修改,只能基於穩定的物理儲存中的資料集建立RDD,或者通過在其他RDD上執行確定的轉換操作(如map、join和group by)而建立得到新的RDD。RDD提供了豐富的操作以支援常見的資料運算,分為“動作”(Action)和“轉換”(Transformation)兩種型別。RDD提供的轉換介面都非常簡單,都是類似map、filter、groupBy、join等粗粒度的資料轉換操作,而不是針對某個資料項的細粒度修改。RDD典型的執行過程如下:1、RDD讀入外部資料來源進行建立。2、RDD經過系列的轉換(Transformation)操作,每一次都會產生不同的RDD,供給下一個轉換操作使用。3、最後一個RDD經過“動作”操作進行轉換,並輸出到外部資料來源。

【Spark任務執行流程】

1、首先為應用構建起基本的執行環境,即由Driver建立一個SparkContext,進行資源的申請、任務的分配和監控。
2、資源管理器為Executor分配資源,並啟動Executor程式。
3、SparkContext根據RDD的依賴關係構建DAG圖,DAG圖提交給DAGScheduler解析成Stage,然後把一個個TaskSet提交給底層排程器TaskScheduler處理;Executor向SparkContext申請Task,Task Scheduler將Task發放給Executor執行,並提供應用程式程式碼。
4、Task在Executor上執行,把執行結果反饋給TaskScheduler和DAGScheduler,執行完畢後寫入資料並釋放所有資源。


476922-84a3043ac1acf93d.PNG
Spark執行流程圖.PNG

【RDD間的依賴關係】

窄依賴:表現為一個父RDD的分割槽對應於一個子RDD的分割槽或多個父RDD的分割槽對應於一個子RDD的分割槽.
寬依賴:表現為存在一個父RDD的一個分割槽對應一個子RDD的多個分割槽。
Spark通過分析各個RDD的依賴關係生成了DAG,再通過分析各個RDD中的分割槽之間的依賴關係來決定如何劃分Stage,具體劃分方法是:

  1. 在DAG中進行反向解析,遇到寬依賴就斷開
  2. 遇到窄依賴就把當前的RDD加入到Stage中
  3. 將窄依賴儘量劃分在同一個Stage中,可以實現流水線計算

【Stage的型別】

Spark Stage的型別包括兩種:ShuffleMapStage和ResultStage,具體如下:

  1. ShuffleMapStage:不是最終的Stage,在它之後還有其他Stage,所以,它的輸出一定需要經過Shuffle過程,並作為後續Stage的輸入;這種Stage是以Shuffle為輸出邊界,其輸入邊界可以是從外部獲取資料,也可以是另一個ShuffleMapStage的輸出,其輸出可以是另一個Stage的開始;在一個Job裡可能有該型別的Stage,也可能沒有該型別Stage;
  2. ResultStage:最終的Stage,沒有輸出,而是直接產生結果或儲存。這種Stage是直接輸出結果,其輸入邊界可以是從外部獲取資料,也可以是另一個ShuffleMapStage的輸出。在一個Job裡必定有該型別Stage。因此,一個Job含有一個或多個Stage,其中至少含有一個ResultStage。

【Spark RDD運算元】

Spark 運算元大致可以分為以下兩類:
1、Transformation 變換/轉換運算元:這種變換並不觸發提交作業,完成作業中間過程處理。
Transformation 操作是延遲計算的,也就是說從一個RDD 轉換生成另一個 RDD 的轉換操作不是馬上執行,需要等到有 Action 操作的時候才會真正觸發運算。典型運算元:map、flatMap、filter、reduceByKey。
2、Action 行動運算元:這類運算元會觸發 SparkContext 提交 Job 作業。
Action 運算元會觸發 Spark 提交作業(Job),並將資料輸出 Spark系統。典型運算元:take、count、savaAsTextFile等。
從小方向來說,Spark 運算元大致可以分為以下三類:
1、Value資料型別的Transformation運算元,這種變換並不觸發提交作業,針對處理的資料項是Value型的資料。
2、Key-Value資料型別的Transfromation運算元,這種變換並不觸發提交 作業,針對處理的資料項是Key-Value型的資料對。
3、Action運算元,這類運算元會觸發SparkContext提交Job作業。

【RDD持久化工作原理】

Spark非常重要的一個功能特性就是可以將RDD 持久化在記憶體中,當對RDD執行持久化操作時,每個節點都會將自己操作的RDD的partition持久化到記憶體中,並且在之後對該RDD的反覆使用中,直接使用記憶體快取的partition,這樣針對一個RDD反覆執行多個操作的場景,就只要對RDD計算一次即可,後面直接使用該RDD ,而不需要計算多次該RDD。RDD持久化對於迭代式演算法和快速互動式應用來說是非常重要的。
要持久化一個RDD,只要呼叫其cache()或者persist()方法即可。在該RDD第一次被計算出來時,就會直接快取在每個節點中。Spark的持久化機制是自動容錯的,如果持久化的RDD的任何partition丟失了,那麼Spark會自動通過其源RDD,使用transformation操作重新計算該partition。
cache()和persist()的區別在於,cache()是persist()的一種簡化方式,cache()的底層就是呼叫的persist()的無參版本,同時就是呼叫persist(MEMORY_ONLY),將資料持久化到記憶體中。如果需要從記憶體中去除快取,那麼可以使用unpersist()方法。

【RDD持久化策略】

  1. MEMORY_ONLY:以非序列化的Java物件的方式持久化在JVM記憶體中。如果記憶體無法完全儲存RDD所有的partition,那麼那些沒有持久化的partition就會在下一次需要使用它的時候,重新被計算。
  2. MEMORY_AND_DISK:同上,但是當某些partition無法儲存在記憶體中時,會持久化到磁碟中。下次需要使用這些partition時,需要從磁碟上讀取。
  3. MEMORY_ONLY_SER:同MEMORY_ONLY,但是會使用Java序列化方式,將Java物件序列化後進行持久化。可以減少記憶體開銷,但是需要進行反序列化,因此會加大CPU開銷。
  4. MEMORY_AND_DSK_SER:同MEMORY_AND_DSK。但是使用序列化方式持久化Java物件。
  5. DISK_ONLY:使用非序列化Java物件的方式持久化,完全儲存到磁碟上。
  6. MEMORY_ONLY_2或者MEMORY_AND_DISK_2等:如果是尾部加了2的持久化級別,表示會將持久化資料複用一份,儲存到其他節點,從而在資料丟失時,不需要再次計算,只需要使用備份資料即可。

【RDD持久化策略選擇原則】

Spark 的儲存級別的選擇,核心問題是在記憶體使用率和 CPU 效率之間進行權衡。建議按下面的過程進行儲存級別的選擇 :

  1. 如果使用預設的儲存級別(MEMORY_ONLY),儲存在記憶體中的 RDD 沒有發生溢位,那麼就選擇預設的儲存級別。預設儲存級別可以最大程度的提高 CPU 的效率,可以使在 RDD 上的操作以最快的速度執行。
  2. 如果記憶體不能全部儲存 RDD,那麼使用 MEMORY_ONLY_SER,並挑選一個快速序列化庫將物件序列化,以節省記憶體空間。使用這種儲存級別,計算速度仍然很快。
  3. 除了在計算該資料集的代價特別高,或者在需要過濾大量資料的情況下,儘量不要將溢位的資料儲存到磁碟。因為,重新計算這個資料分割槽的耗時與從磁碟讀取這些資料的耗時差不多。
  4. 如果想快速還原故障,建議使用多副本儲存級別(例如,使用 Spark 作為 web 應用的後臺服務,在服務出故障時需要快速恢復的場景下)。所有的儲存級別都通過重新計算丟失的資料的方式,提供了完全容錯機制。但是多副本級別在發生資料丟失時,不需要重新計算對應的資料庫,可以讓任務繼續執行。

【Spark共享變數】

Spark中的兩個重要抽象是RDD和共享變數。在預設情況下,當Spark在叢集的多個不同節點的多個任務上並行執行一個函式時,它會把函式中涉及到的每個變數,在每個任務上都生成一個副本,更新這些副本的值也不會影響驅動器中的對應變數。但是有時候需要在多個任務之間共享變數,或者在任務(Task)和任務控制節點(Driver Program)之間共享變數。為了滿足這種需求,Spark提供了兩種型別的變數:廣播變數(broadcast variables)和累加器(accumulators)。廣播變數用來把變數在所有節點的記憶體之間進行共享。累加器則支援在所有不同節點之間進行累加計算(比如計數或者求和)。

【廣播變數(broadcast variable)】

廣播變數用來高效分發較大的公共物件。如果要在分散式計算裡面分發大物件,例如:字典,集合等,都由Driver端進行分發,廣播變數允許在每個機器上快取一個只讀的變數,而不是為每個任務都生成一個副本。如果這個變數不是廣播變數,那麼每個task就會分發一份,這在task數目十分多的情況下Driver的頻寬會成為系統的瓶頸,而且會大量消耗task伺服器上的資源,如果將這個變數宣告為廣播變數,那麼只是每個executor擁有一份,這個executor啟動的task會共享這個變數,節省了通訊的成本和伺服器的資源。通過這種方式,就可以非常高效地給每個節點提供一個大的輸入資料集的副本。Spark的“動作”操作會跨越多個階段(stage),對於每個階段內的所有任務所需要的公共資料,Spark都會自動進行廣播,通過廣播方式進行傳播的變數。廣播變數在Driver端定義,只能在Driver端改變廣播變數的值,Executor端無法修改。

【累加器(Accumulator)】

累加器用來對資訊進行聚合,累加器是僅僅被相關操作累加的變數,通常可以被用來實現計數器(counter)和求和(sum)。Spark原生支援數值型(numeric)的累加器,程式開發人員可以編寫對新型別的支援。如果建立累加器時指定了名字,則可以在Spark UI介面看到,這有利於理解每個執行階段的程式。
一個數值型的累加器,可以通過呼叫SparkContext.accumulator()來建立。執行在叢集中的任務,就可以使用add方法來把數值累加到累加器上,但是,這些任務只能做累加操作,不能讀取累加器的值,只有任務控制節點(Driver Program)可以使用value方法來讀取累加器的值。
累加器提供了將工作節點中的值聚合到驅動器程式中的語法。解決driver和excutor端的資料不能共享的問題。累加器在Driver端定義賦初始值,且只能在Driver端讀取,在Excutor端更新。常用在除錯時對作業執行過程中的事件進行計數。

【Spark SQL】

Spark SQL是Spark中用於結構化資料處理的模組。與基礎的Spark RDD API不同,Spark SQL的介面提供了更多關於資料的結構資訊和計算任務的執行時資訊。在Spark應用中,可以無縫的使用SQL語句亦或是DataFrame API對結構化資料程式查詢。
Spark SQL有以下幾個特點:

  1. 資料相容:可從Hive表、外部資料庫(JDBC)、RDD、Parquet檔案、JSON檔案獲取資料,可通過Scala方法或SQL方式操作這些資料,並把結果轉回RDD。
  2. 元件擴充套件:SQL語法解析器、分析器、優化器均可重新定義。
  3. 效能優化:記憶體列儲存、動態位元組碼生成等優化技術,記憶體快取資料。
  4. 多語言支援:Scala、Java、Python、R。

【Spark SQL的優點】

1、整合:Apache Spark SQL將SQL查詢與Spark程式整合。可以將結構化資料作為分散式資料集(RDD)查詢,可以使用Spark SQL緊密整合屬性與複雜的分析演算法一起執行SQL查詢。
2、統一資料訪問:使用Spark SQL,可以載入和查詢不同來源資料。Schema-RDD允許單個介面高效處理結構化資料。例如,Apache Hive tables, parquet files, and JSON files.
3、高相容性:在Apache Spark SQL中,可以在現有倉庫上執行未修改的Hive查詢,相容現有Hive資料以及UDF。
4、標準連線:可通過JDBC或ODBC連線,包括具有行業標準JDBC和ODBC連線的伺服器模式。
5、可擴充套件性:為了支援查詢容錯和大型作業,利用了RDD模型,使用相同的引擎進行互動式查詢。
6、效能優化:Spark SQL中的查詢優化引擎在整個計劃中選擇最佳的執行計劃。

【Spark SQL之DataFrame】

DataFrame是一個以命名列方式組織的分散式資料集。在概念上類似於關係型資料庫中的一張表。DataFrame讓Spark具備了處理大規模結構化資料的能力,不僅比原有的RDD轉化方式更加簡單易用,而且獲得了更高的計算效能。RDD是分散式的 Java物件的集合,比如,RDD[Person]是以Person為型別引數,但是,Person類的內部結構對於RDD而言卻是不可知的。DataFrame是一種以RDD為基礎的分散式資料集,也就是分散式的Row物件的集合(每個Row物件代表一行記錄),提供了詳細的結構資訊,也就是常說的模式(schema),Spark SQL可以清楚地知道該資料集中包含哪些列、每列的名稱和型別。和RDD一樣,DataFrame的各種變換操作也採用惰性機制,只是記錄了各種轉換的邏輯轉換路線圖(DAG圖),不會發生真正的計算,這個DAG圖相當於一個邏輯查詢計劃,最終,會被翻譯成物理查詢計劃,生成RDD DAG,按照RDD DAG的執行方式去完成最終的計算得到結果。

【Hive on Mapreduce VS SparkSQL】

適用場景上:Hive on Mapreduce的出現可以讓那些精通SQL技能、但是不熟悉MapReduce 、程式設計能力較弱與不擅長Java語言的使用者能夠在HDFS大規模資料集上很方便地利用SQL 語言查詢、彙總、分析資料,畢竟精通SQL語言的人要比精通Java語言的多得多,Hive適合處理離線非實時資料。
SparkSQL既可以執行本地local模式,也可以以Standalone、cluster等多種模式執行在Yarn、Mesos上,還可以執行在雲端例如EC2。此外,Spark的資料來源非常廣泛,可以處理來自HDFS、HBase、 Hive、Cassandra、Tachyon上的各種型別的資料。適用於實時性要求或者速度要求較高的場所。
效能上:sparksql和hive on spark時間差不多,但都比hive on mapreduce快很多,官方資料認為spark會被傳統mapreduce快10-100倍。

【Spark MLlib】

MLlib是Spark的機器學習(ML)庫。旨在簡化機器學習的工程實踐工作,並方便擴充套件到更大規模。MLlib由一些通用的學習演算法和工具組成,包括:1.機器學習演算法:如常規機器學習演算法包括分類、迴歸、聚類和協同過濾。2.特徵工程:特徵提取、特徵轉換、特徵選擇以及降維。3.管道:構造、評估和調整的管道的工具。4.儲存:儲存和載入演算法、模型及管道。5.實用工具:線性代數,統計,資料處理等。
MLlib目前分為兩個程式碼包:spark.mllib 包含基於RDD的原始演算法API。spark.ml 則提供了基於DataFrames 高層次的API,可以用來構建機器學習管道。推薦使用spark.ml,因為基於DataFrames的API更加通用而且靈活,包括Spark資料來源,SQL/DataFrame查詢,為多種機器學習演算法與程式語言提供統一的API,DataFrames有助於實現機器學習管道,特別是特徵轉換。spark2.0開始,基於RDD的API已經進入的維護模式。

【Spark Streaming】

Spark streaming是Spark核心API的一個擴充套件,它對實時流式資料的處理具有可擴充套件性、高吞吐量、可容錯性等特點。可以從kafka、flume、Twitter、ZeroMQ、Kinesis等源獲取資料,也可以通過由高階函式map、reduce、join、window等組成的複雜演算法計算出資料。最後,處理後的資料可以推送到檔案系統、資料庫、實時儀表盤中,或者可以將處理後的資料應用到Spark的機器學習演算法、圖處理演算法中去。(資料流是連續到達的無窮序列。流處理將不斷流動的輸入資料分成獨立的單元進行處理。流處理是對流資料的低延遲處理和分析。實時處理用例包括:網站監控,網路監控,欺詐識別,網頁點選,廣告,物聯網感測器等。)

相關文章