Spark2.1.0模型設計與基本架構(上)
隨著近十年網際網路的迅猛發展,越來越多的人融入了網際網路——利用搜索引擎查詢詞條或問題;社交圈子從現實搬到了Facebook、Twitter、微信等社交平臺上;女孩子們現在少了逛街,多了在各大電商平臺上的購買;喜歡棋牌的人能夠在對戰平臺上找到世界各地的玩家對弈。在國內隨著網民數量的持續增加,造成網際網路公司的資料在體量、產生速度、多樣性等方面呈現出巨大的變化。
網際網路產生的資料相較於傳統軟體產生的資料,有著資料探勘的巨大潛力。通過對資料的挖掘,可以統計出PV、UV,計算出不同裝置與註冊率、促銷與下單率之間的關係,甚至構建熱點分析、人群畫像等演算法模型,產生一系列報表、圖形、離線統計、實時計算的產品。網際網路公司如果能有效利用這些資料,將對決策和戰略發展起到至關重要的作用。
在大資料的大勢之下,Hadoop、Spark、Flink、Storm、Dremel、Impala、Tez等一系列大資料技術如雨後春筍般不斷湧現。工程師們正在使用這些工具在摸索中前行。
Spark是一個通用的平行計算框架,由加州伯克利大學(UCBerkeley)的AMP實驗室開發於2009年,並於2010年開源。2013年成長為Apache旗下在大資料領域最活躍的開源專案之一。
Spark目前已經走過了0.x和1.x兩個時代,現在正在2.x時代穩步發展。Spark從2012年10月15日釋出0.6到2016年1月4日釋出1.6只經過了三年時間,那時候差不多每個月都會有新的版本釋出,平均每個季度會發佈一個新的二級版本。
自從2016年7月釋出了2.0.0版本以來,只在當年12月又釋出了2.1.0版本,直到目前為止還沒有新的二級版本釋出。Spark釋出新版本的節奏明顯慢了下來,當然這也跟Spark團隊過於激進的決策(比如很多API不能向前相容,讓使用者無力吐槽)有關。
Spark也是基於map reduce 演算法模型實現的分散式計算框架,擁有Hadoop MapReduce所具有的優點,並且解決了Hadoop MapReduce中的諸多缺陷。
Hadoop MRv1的侷限
早在Hadoop1.0版本,當時採用的是MRv1版本的MapReduce程式設計模型。MRv1版本的實現都封裝在org.apache.hadoop.mapred包中,MRv1的Map和Reduce是通過介面實現的。MRv1包括三個部分:
- 執行時環境(JobTracker和TaskTracker);
- 程式設計模型(MapReduce);
- 資料處理引擎(Map任務和Reduce任務)。
MRv1存在以下不足。
- 可擴充套件性差:在執行時,JobTracker既負責資源管理又負責任務排程,當叢集繁忙時,JobTracker很容易成為瓶頸,最終導致它的可擴充套件性問題。
- 可用性差:採用了單節點的Master,沒有備用Master及選舉操作,這導致一旦Master出現故障,整個叢集將不可用。
- 資源利用率低:TaskTracker 使用slot等量劃分本節點上的資源量。slot代表計算資源(CPU、記憶體等)。一個Task 獲取到一個slot 後才有機會執行,Hadoop 排程器負責將各個TaskTracker 上的空閒slot 分配給Task 使用。一些Task並不能充分利用slot,而其他Task也無法使用這些空閒的資源。slot 分為Map slot 和Reduce slot 兩種,分別供MapTask 和Reduce Task 使用。有時會因為作業剛剛啟動等原因導致MapTask很多,而Reduce Task任務還沒有排程的情況,這時Reduce slot也會被閒置。
- 不能支援多種MapReduce框架:無法通過可插拔方式將自身的MapReduce框架替換為其他實現,如Spark、Storm等。
MRv1的示意如圖1。
圖1 MRv1示意圖
Apache為了解決以上問題,對Hadoop升級改造,MRv2最終誕生了。MRv2中,重用了MRv1中的程式設計模型和資料處理引擎。但是執行時環境被重構了。JobTracker被拆分成了通用的資源排程平臺(ResourceManager,簡稱RM)、節點管理器(NodeManager)和負責各個計算框架的任務排程模型(ApplicationMaster,簡稱AM)。ResourceManager依然負責對整個叢集的資源管理,但是在任務資源的排程方面只負責將資源封裝為Container分配給ApplicationMaster 的一級排程,二級排程的細節將交給ApplicationMaster去完成,這大大減輕了ResourceManager 的壓力,使得ResourceManager 更加輕量。NodeManager負責對單個節點的資源管理,並將資源資訊、Container執行狀態、健康狀況等資訊上報給ResourceManager。ResourceManager 為了保證Container的利用率,會監控Container,如果Container未在有限的時間內使用,ResourceManager將命令NodeManager殺死Container,以便於將資源分配給其他任務。MRv2的核心不再是MapReduce框架,而是Yarn。在以Yarn為核心的MRv2中,MapReduce框架是可插拔的,完全可以替換為其他MapReduce實現,比如Spark、Storm等。MRv2的示意如圖2所示。
圖2 MRv2示意圖
Hadoop MRv2雖然解決了MRv1中的一些問題,但是由於對HDFS的頻繁操作(包括計算結果持久化、資料備份、資源下載及Shuffle等)導致磁碟I/O成為系統性能的瓶頸,因此只適用於離線資料處理或批處理,而不能支援對迭代式、流式資料的處理。
Spark的特點
Spark看到MRv2的問題,對MapReduce做了大量優化,總結如下:
- 減少磁碟I/O:隨著實時大資料應用越來越多,Hadoop作為離線的高吞吐、低響應框架已不能滿足這類需求。HadoopMapReduce的map端將中間輸出和結果儲存在磁碟中,reduce端又需要從磁碟讀寫中間結果,勢必造成磁碟IO成為瓶頸。Spark允許將map端的中間輸出和結果儲存在記憶體中,reduce端在拉取中間結果時避免了大量的磁碟I/O。Hadoop Yarn中的ApplicationMaster申請到Container後,具體的任務需要利用NodeManager從HDFS的不同節點下載任務所需的資源(如Jar包),這也增加了磁碟I/O。Spark將應用程式上傳的資原始檔緩衝到Driver本地檔案服務的記憶體中,當Executor執行任務時直接從Driver的記憶體中讀取,也節省了大量的磁碟I/O。
- 增加並行度:由於將中間結果寫到磁碟與從磁碟讀取中間結果屬於不同的環節,Hadoop將它們簡單的通過序列執行銜接起來。Spark把不同的環節抽象為Stage,允許多個Stage既可以序列執行,又可以並行執行。
- 避免重新計算:當Stage中某個分割槽的Task執行失敗後,會重新對此Stage排程,但在重新排程的時候會過濾已經執行成功的分割槽任務,所以不會造成重複計算和資源浪費。
- 可選的Shuffle排序:HadoopMapReduce在Shuffle之前有著固定的排序操作,而Spark則可以根據不同場景選擇在map端排序或者reduce端排序。
- 靈活的記憶體管理策略:Spark將記憶體分為堆上的儲存記憶體、堆外的儲存記憶體、堆上的執行記憶體、堆外的執行記憶體4個部分。Spark既提供了執行記憶體和儲存記憶體之間是固定邊界的實現,又提供了執行記憶體和儲存記憶體之間是“軟”邊界的實現。Spark預設使用“軟”邊界的實現,執行記憶體或儲存記憶體中的任意一方在資源不足時都可以借用另一方的記憶體,最大限度的提高資源的利用率,減少對資源的浪費。Spark由於對記憶體使用的偏好,記憶體資源的多寡和使用率就顯得尤為重要,為此Spark的記憶體管理器提供的Tungsten實現了一種與作業系統的記憶體Page非常相似的資料結構,用於直接操作作業系統記憶體,節省了建立的Java物件在堆中佔用的記憶體,使得Spark對記憶體的使用效率更加接近硬體。Spark會給每個Task分配一個配套的任務記憶體管理器,對Task粒度的記憶體進行管理。Task的記憶體可以被多個內部的消費者消費,任務記憶體管理器對每個消費者進行Task記憶體的分配與管理,因此Spark對記憶體有著更細粒度的管理。
基於以上所列舉的優化,Spark官網聲稱效能比Hadoop快100倍,如圖3所示。即便是記憶體不足需要磁碟I/O時,其速度也是Hadoop的10倍以上。
圖3 Hadoop與Spark執行邏輯迴歸時間比較
Spark還有其他一些特點。
- 檢查點支援:Spark的RDD之間維護了血緣關係(lineage),一旦某個RDD失敗了,則可以由父RDD重建。雖然lineage可用於錯誤後RDD的恢復,但對於很長的lineage來說,恢復過程非常耗時。如果應用啟用了檢查點,那麼在Stage中的Task都執行成功後,SparkContext將把RDD計算的結果儲存到檢查點,這樣當某個RDD執行失敗後,在由父RDD重建時就不需要重新計算,而直接從檢查點恢復資料。
- 易於使用。Spark現在支援Java、Scala、Python和R等語言編寫應用程式,大大降低了使用者的門檻。自帶了80多個高等級操作符,允許在Scala,Python,R的shell中進行互動式查詢。
- 支援互動式:Spark使用Scala開發,並藉助於Scala類庫中的Iloop實現互動式shell,提供對REPL(Read-eval-print-loop)的實現。
- 支援SQL查詢。在資料查詢方面,Spark支援SQL及Hive SQL,這極大的方便了傳統SQL開發和資料倉庫的使用者。
- 支援流式計算:與MapReduce只能處理離線資料相比,Spark還支援實時的流計算。Spark依賴SparkStreaming對資料進行實時的處理,其流式處理能力還要強於Storm。
- 可用性高。Spark自身實現了Standalone部署模式,此模式下的Master可以有多個,解決了單點故障問題。Spark也完全支援使用外部的部署模式,比如YARN、Mesos、EC2等。
- 豐富的資料來源支援:Spark除了可以訪問作業系統自身的檔案系統和HDFS,還可以訪問Kafka、Socket、Cassandra、HBase、Hive、Alluxio(Tachyon)以及任何Hadoop的資料來源。這極大地方便了已經使用HDFS、HBase的使用者順利遷移到Spark。
- 豐富的檔案格式支援:Spark支援文字檔案格式、Csv檔案格式、Json檔案格式、Orc檔案格式、Parquet檔案格式、Libsvm檔案格式,也有利於Spark與其他資料處理平臺的對接。
Spark使用場景
Hadoop常用於解決高吞吐、批量處理的業務場景,例如對瀏覽量的離線統計。如果需要實時檢視瀏覽量統計資訊,Hadoop顯然不符合這樣的要求。Spark通過記憶體計算能力極大地提高了大資料處理速度,滿足了以上場景的需要。此外,Spark還支援互動式查詢,SQL查詢,流式計算,圖計算,機器學習等。通過對Java、Python、Scala、R等語言的支援,極大地方便了使用者的使用。
筆者就目前所知道的Spark應用場景,進行介紹。
1.醫療健康
看病是一個非常典型的分析過程——醫生根據患者的一些徵兆、檢驗結果,結合醫生本人的經驗得出結論,最後給出相應的治療方案。現在國內的醫療狀況是各地區醫療水平參差不齊,醫療資源也非常緊張,特別是高水平醫生更為緊缺,好醫院的地區分佈很不均衡。大城市有更完善的醫療體系,而農村可能就只有幾個赤腳醫生。一些農民看病可能要從村裡坐車到鎮,再到縣城,再到地級市甚至省會城市,看病的路程堪比征程。
大資料根據患者的患病徵兆、檢驗報告,通過病理分析模型找出病因並給出具體的治療方案。即便是醫療水平落後的地區,只需要輸入患者的患病徵兆和病例資料既可體驗高水平醫師的服務。通過Spark從海量資料中實時計算出病因,各個地區的醫療水平和效率將獲得大幅度提升,同時也能很好的降低因為醫生水平而導致誤診的概率。
實施醫療健康的必然措施是監測和預測。通過監測不斷更新整個醫療基礎庫的知識,並通過醫療健康模型預測出疾病易發的地區和人群。
2.電商
通過對使用者的消費習慣、季節、產品使用週期等資料的收集,建立演算法模型來判斷消費者未來一個月、幾個月甚至一年的消費需求(不是簡單的根據你已經消費的產品,顯示推薦廣告位),進而提高訂單轉化率。
在市場營銷方面,通過給買家打標籤,構建人群畫像,進而針對不同的人群,精準投放廣告、紅包或優惠券。
3.安全領域
面對日益複雜的網路安全,通過檢測和資料分析區分出不同的安全型別。並針對不同的安全型別,實施不同的防禦、打擊措施。
- 端安全:使用安全衛士、雲查殺對經過大資料分析得到的病毒、木馬等進行防禦。
- 電商安全:反刷單、反欺詐、合規。
- 金融安全:風險控制。
- 企業安全:反入侵。
- 國家安全:輿情監測,打擊罪犯。
4.金融領域
構建金融雲,通過對巨量的計量資料收集。通過Spark實時處理分析,利用低延遲的資料處理能力,應對急迫的業務需求和資料增長。
量化投資——收集大宗商品的價格,黃金,石油等各種資料,分析黃金、股票等指數趨勢,支援投資決策。
除了以上領域外,在搜尋引擎、生態圈異常檢測、生物計算等諸多領域都有廣泛的應用場景。
版本變遷
經過5年多的發展,Spark目前的大版本是2.3.0。Spark主要版本的發展過程如下:
- Spark誕生於UCBerkeley的AMP實驗室(2009)。
- Spark正式對外開源(2010)。
- Spark 0.6.0版本釋出(2012-10-15),大範圍的效能改進,增加了一些新特性,並對Standalone部署模式進行了簡化。
- Spark 0.7.0版本釋出(2013-02-27),增加了更多關鍵特性,例如:PythonAPI、Spark Streaming的alpha版本等。
- Spark接受進入Apache孵化器(2013-06-21)。
- Spark 0.8.0版本釋出(2013-09-25),一些新功能及可用性改進。
- Spark 0.8.1版本釋出(2013-12-19),支援Scala 2.9,YARN 2.2,Standalone部署模式下排程的高可用性,shuffle的優化等。
- Spark 0.9.0版本釋出(2014-02-02),增加了GraphX、機器學習、流式計算等新特性,對核心引擎的優化(外部聚合、加強對YARN的支援)等。
- Spark 1.0.0版本釋出(2014-05-30),增加了Spark SQL。對MLlib、GraphX和Spark Streaming都增加了新特性並進行了優化。Spark核心引擎還增加了對安全YARN叢集的支援。
- Spark 1.1.0版本釋出(2014-09-11)。對MLlib andSpark SQL進行了顯著的擴充套件等。
- Spark 1.2.0版本釋出(2014-12-18),Spark SQL增加了對HIVE 13、動態分割槽的支援,SparkStreaming增加了Python語言的API等。
- Spark 1.3.0版本釋出(2015-03-13),在Spark SQL 中增加了DataFrameAPI。
- Spark 1.4.0版本釋出(2015-06-11),增加了R語言的API,對Spark核心引擎的可用性進行了改進,對MLlib和Spark Streaming進行了擴充套件。
- Spark 1.5.0版本釋出(2015-09-09),對各種功能和API進行了修改或改進。
- Spark 1.6.0版本釋出(2016-01-04),對Spark Core、Spark SQL、Spark Streaming、MLlib的API進行了改進,對SparkCore和Spark SQL的效能進行了優化。
- Spark 2.0.0版本釋出(2016-07-26),增加API的穩定性,對SQL 2003標準的支援,效能的優化,結構化的Streaming,R語言UDF的支援等。
- Spark 2.1.0版本釋出(2016-12-28),主要對結構化的Streaming進行了改進。
- Spark 2.2.0版本釋出(2017-07-11),正式提供非實驗性質的結構化的Streaming。
- Spark 2.3.0版本釋出(2018-02-28),增加結構化Streaming的連續處理,Kubernetes的排程後端。
基本概念
要想對Spark有整體性的瞭解,推薦讀者閱讀Matei Zaharia的Spark論文。此處筆者先介紹Spark中的一些概念:
- RDD(resillient distributed dataset):彈性分散式資料集。Spark應用程式通過使用Spark的轉換API可以將RDD封裝為一系列具有血緣關係的RDD,也就是DAG。只有通過Spark的動作API才會將RDD及其DAG提交到DAGScheduler。RDD的祖先一定是一個跟資料來源相關的RDD,負責從資料來源迭代讀取資料。
- DAG(Directed Acycle graph):有向無環圖。在圖論中,如果一個有向圖無法從某個頂點出發經過若干條邊回到該點,則這個圖是一個有向無環圖(DAG圖)。Spark使用DAG來反映各RDD之間的依賴或血緣關係。
- Partition:資料分割槽。即一個RDD的資料可以劃分為多少個分割槽。Spark根據Partition的數量來確定Task的數量。
- NarrowDependency:窄依賴。即子RDD依賴於父RDD中固定的Partition。NarrowDependency分為OneToOneDependency和RangeDependency兩種。
- ShuffleDependency:Shuffle依賴,也稱為寬依賴。即子RDD對父RDD中的所有Partition都可能產生依賴。子RDD對父RDD各個Partition的依賴將取決於分割槽計算器(Partitioner)的演算法。
- Job:使用者提交的作業。當RDD及其DAG被提交給DAGScheduler排程後,DAGScheduler會將所有RDD中的轉換及動作視為一個Job。一個Job由一到多個Task組成。
- Stage:Job的執行階段。DAGScheduler按照ShuffleDependency作為Stage的劃分節點對RDD的DAG進行Stage劃分(上游的Stage將為ShuffleMapStage)。因此一個Job可能被劃分為一到多個Stage。Stage分為ShuffleMapStage和ResultStage兩種。
- Task:具體執行任務。一個Job在每個Stage內都會按照RDD的Partition 數量,建立多個Task。Task分為ShuffleMapTask和ResultTask兩種。ShuffleMapStage中的Task為ShuffleMapTask,而ResultStage中的Task為ResultTask。ShuffleMapTask和ResultTask類似於Hadoop中的 Map任務和Reduce任務。
Scala與Java的比較
目前越來越多的語言可以執行在Java虛擬機器上,Java平臺上的多語言混合程式設計正成為一種潮流。在混合程式設計模式下可以充分利用每種語言的特點和優勢,以便更好地完成功能。Spark同時選擇了Scala和Java作為開發語言,也是為了充分利用二者各自的優勢。表1對這兩種語言進行比較。
表1 Scala與Java的比較
Scala |
Java |
|
語言型別 |
面向函式為主,兼有面向物件 |
面向物件(Java8也增加了lambda函式程式設計) |
簡潔性 |
非常簡潔 |
不簡潔 |
型別推斷 |
豐富的型別推斷,例如深度和鏈式的型別推斷、 duck type 、隱式型別轉換等,但也因此增加了編譯時長 |
少量的型別推斷 |
可讀性 |
一般,豐富的語法糖導致的各種奇幻用法,例如方法簽名、隱式轉換 |
好 |
學習成本 |
較高 |
一般 |
語言特性 |
非常豐富的語法糖和更現代的語言特性,例如 Option 、模式匹配、使用空格的方法呼叫 |
豐富 |
併發程式設計 |
使用Actor的訊息模型 |
使用阻塞、鎖、阻塞佇列等 |
注意:雖然Actor是Scala語言最初進行推廣時,最吸引人的特性之一,但是隨著Akka更加強大的Actor類庫的出現,Scala已經在官方網站宣佈廢棄Scala自身的Actor程式設計模型,轉而全面擁抱Akka提供的Actor程式設計模型。與此同時,從Spark2.0.0版本開始,Spark卻放棄了使用Akka,轉而使用Netty實現了自己的Rpc框架。遙想當年Scala“鼓吹”Actor程式設計模型優於Java的同步程式設計模型時,又有誰會想到如今這種場面呢?
Scala作為函數語言程式設計的代表,天生適合並行執行,如果用Java語言實現相同的功能會顯得非常臃腫。很多介紹Spark的新聞或文章經常以Spark核心程式碼行數少或API精煉等內容作為宣傳的“法器”,這應該也是選擇Scala的原因之一。另一方面,由於函數語言程式設計更接近計算機思維,因此便於通過演算法從大資料中建模,這也更符合Spark作為大資料框架的理念吧!
由於Java適合伺服器、中介軟體開發,所以Spark使用Java更多的是開發底層的基礎設施或中介軟體。
模組設計
整個Spark主要由以下模組組成:
- Spark Core:Spark的核心功能實現,包括:基礎設施、SparkContext(Application通過SparkContext提交)、Spark執行環境(SparkEnv)、儲存體系、排程系統、計算引擎、部署模式、任務提交與執行等。
- Spark SQL:提供SQL處理能力,便於熟悉關係型資料庫操作的工程師進行互動查詢。此外,還為熟悉Hive開發的使用者提供了對Hive SQL的支援。
- Spark Streaming:提供流式計算處理能力,目前支援ApacheKafka、Apache Flume、Amazon Kinesis和簡單的TCP套接字等資料來源。在早期的Spark版本中還自帶對Twitter、MQTT、ZeroMQ等的支援,現在使用者想要支援這些工具必須自己開發實現。此外,Spark Streaming還提供視窗操作用於對一定週期內的流資料進行處理。
- GraphX:基於圖論,實現的支援分散式的圖計算處理框架。GraphX的基礎是點、邊等圖論的理論。GraphX 基於圖計算的Pregel模型提供了多種多樣的Pregel API,這些Pregel API可以解決圖計算中的常見問題。
- MLlib:Spark提供的機器學習庫。MLlib提供了機器學習相關的統計、分類、迴歸等領域的多種演算法實現。其一致的API介面大大降低了使用者的學習成本。
Spark SQL、Spark Streaming、GraphX、MLlib的能力都是建立在核心引擎之上,如圖4。
圖4 Spark各模組依賴關係
Spark核心功能
Spark Core中提供了Spark最基礎與最核心的功能,主要包括:
- 基礎設施:在Spark中有很多基礎設施,被Spark中的各種元件廣泛使用。這些基礎設施包括Spark配置(SparkConf)、Spark內建的Rpc框架(在早期Spark版本中Spark使用的是Akka)、事件匯流排(ListenerBus)、度量系統。SparkConf用於管理Spark應用程式的各種配置資訊。Spark內建的Rpc框架使用Netty實現,有同步和非同步的多種實現,Spark各個元件間的通訊都依賴於此Rpc框架。如果說Rpc框架是跨機器節點不同元件間的通訊設施,那麼事件匯流排就是SparkContext內部各個元件間使用事件——監聽器模式非同步呼叫的實現。度量系統由Spark中的多種度量源(Source)和多種度量輸出(Sink)構成,完成對整個Spark叢集中各個元件執行期狀態的監控。
- SparkContext:通常而言,使用者開發的Spark應用程式(Application)的提交與執行都離不開SparkContext的支援。在正式提交Application之前,首先需要初始化SparkContext。SparkContext隱藏了網路通訊、分散式部署、訊息通訊、儲存體系、計算引擎、度量系統、檔案服務、Web UI等內容,應用程式開發者只需要使用SparkContext提供的API完成功能開發。
- SparkEnv:Spark執行環境(SparkEnv)是Spark中的Task執行所必須的元件。SparkEnv內部封裝了Rpc環境(RpcEnv)、序列化管理器、廣播管理器(BroadcastManager)、map任務輸出跟蹤器(MapOutputTracker)、儲存體系、度量系統(MetricsSystem)、輸出提交協調器(OutputCommitCoordinator)等Task執行所需的各種元件。
- 儲存體系:Spark優先考慮使用各節點的記憶體作為儲存,當記憶體不足時才會考慮使用磁碟,這極大地減少了磁碟I/O,提升了任務執行的效率,使得Spark適用於實時計算、迭代計算、流式計算等場景。在實際場景中,有些Task是儲存密集型的,有些則是計算密集型的,所以有時候會造成儲存空間很空閒,而計算空間的資源又很緊張。Spark的記憶體儲存空間與執行儲存空間之間的邊界可以是“軟”邊界,因此資源緊張的一方可以借用另一方的空間,這既可以有效利用資源,又可以提高Task的執行效率。此外,Spark的記憶體空間還提供了Tungsten的實現,直接操作作業系統的記憶體。由於Tungsten省去了在堆內分配Java物件,因此能更加有效的利用系統的記憶體資源,並且因為直接作業系統記憶體,空間的分配和釋放也更迅速。在Spark早期版本還使用了以記憶體為中心的高容錯的分散式檔案系統Alluxio(Tachyon)供使用者進行選擇。Alluxio能夠為Spark提供可靠的記憶體級的檔案共享服務。
- 排程系統:排程系統主要由DAGScheduler和TaskScheduler組成,它們都內建在SparkContext中。DAGScheduler負責建立Job、將DAG中的RDD劃分到不同的Stage、給Stage建立對應的Task、批量提交Task等功能。TaskScheduler負責按照FIFO或者FAIR等排程演算法對批量Task進行排程;為Task分配資源;將Task傳送到叢集管理器分配給當前應用的Executor上由Executor負責執行等工作。現如今,Spark增加了SparkSession和DataFrame等新的API,SparkSession底層實際依然依賴於SparkContext。
- 計算引擎:計算引擎由記憶體管理器(MemoryManager)、Tungsten、任務記憶體管理器(TaskMemoryManager)、Task、外部排序器(ExternalSorter)、Shuffle管理器(ShuffleManager)等組成。MemoryManager除了對儲存體系中的儲存記憶體提供支援和管理,還外計算引擎中的執行記憶體提供支援和管理。Tungsten除用於儲存外,也可以用於計算或執行。TaskMemoryManager對分配給單個Task的記憶體資源進行更細粒度的管理和控制。ExternalSorter用於在map端或reduce端對ShuffleMapTask計算得到的中間結果進行排序、聚合等操作。ShuffleManager用於將各個分割槽對應的ShuffleMapTask產生的中間結果持久化到磁碟,並在reduce端按照分割槽遠端拉取ShuffleMapTask產生的中間結果。
Spark擴充套件功能
為了擴大應用範圍,Spark陸續增加了一些擴充套件功能,主要包括:
- Spark SQL:由於SQL具有普及率高、學習成本低等特點,為了擴大Spark的應用面,因此增加了對SQL及Hive的支援。Spark SQL的過程可以總結為:首先使用SQL語句解析器(SqlParser)將SQL轉換為語法樹(Tree),並且使用規則執行器(RuleExecutor)將一系列規則(Rule)應用到語法樹,最終生成物理執行計劃並執行的過程。其中,規則包括語法分析器(Analyzer)和優化器(Optimizer)。Hive的執行過程與SQL類似。
- Spark Streaming:Spark Streaming與Apache Storm類似,也用於流式計算。SparkStreaming支援Kafka、Flume、Kinesis和簡單的TCP套接字等多種資料輸入源。輸入流接收器(Receiver)負責接入資料,是接入資料流的介面規範。Dstream是Spark Streaming中所有資料流的抽象,Dstream可以被組織為DStreamGraph。Dstream本質上由一系列連續的RDD組成。
- GraphX:Spark提供的分散式圖計算框架。GraphX主要遵循整體同步平行計算模式(Bulk Synchronous Parallell,簡稱BSP)下的Pregel模型實現。GraphX提供了對圖的抽象Graph,Graph由頂點(Vertex)、邊(Edge)及繼承了Edge的EdgeTriplet(添加了srcAttr和dstAttr用來儲存源頂點和目的頂點的屬性)三種結構組成。GraphX目前已經封裝了最短路徑、網頁排名、連線元件、三角關係統計等演算法的實現,使用者可以選擇使用。
- MLlib:Spark提供的機器學習框架。機器學習是一門涉及概率論、統計學、逼近論、凸分析、演算法複雜度理論等多領域的交叉學科。MLlib目前已經提供了基礎統計、分類、迴歸、決策樹、隨機森林、樸素貝葉斯、保序迴歸、協同過濾、聚類、維數縮減、特徵提取與轉型、頻繁模式挖掘、預言模型標記語言、管道等多種數理統計、概率論、資料探勘方面的數學演算法。
引用:本文的圖1和圖2都來源自http://blog.chinaunix.net/uid-28311809-id-4383551.html。