我必須要說,Spark這個框架出現之前,我對很多大數據領域的框架源碼甚至都是嗤之以鼻的。
很多小夥伴在群裡或者私信留言問我關於Spark的學習路徑問題。
Spark發展至今,應該說已經非常成熟了。是大數據計算領域不得不學習的框架。尤其是Spark在穩定性和社區發展的成熟度方面,基本可以吊打其他的大數據處理框架。
Spark的背景和核心論文假如你是第一次接觸Spark,那麼你需要對Spark的設計思想有所了解,知道Spark用了哪些抽象,Spark在提出RDD的時候是基於什麼樣的考慮。
在這裡給大家推薦幾篇論文如下:
https://fasionchan.com/blog/2017/10/19/yi-wen-tan-xing-fen-bu-shi-shu-ju-ji-yi-zhong-wei-nei-cun-hua-ji-qun-ji-suan-she-ji-de-rong-cuo-mo-xing/
這篇文章中提出了彈性分布式數據集(RDD,Resilient Distributed Datasets)這個概念,這個概念是貫穿Spark設計的始終,是Spark最重要的概念之一。RDD是一種分布式的內存抽象,允許在大型集群上執行基於內存的計算(In-Memory Computing),與此同時還保持了MapReduce等數據流模型的容錯特性。
這篇文章中提到,Spark實現RDD在迭代計算方面比Hadoop快二十多倍,同時還可以在5-7秒的延時內交互式地查詢1TB的數據集。
- 第二篇:《大型集群上的快速和通用數據處理架構》
這本書我不給連接了。因為這個文章長達170多頁,堪比一篇博士論文。相信絕大多數人都是沒興趣讀完的。
我在這裡給出一個讀後小總結:
這本書是Spark框架設計者–計算機科學博士Matei Alexandru Zaharia和加州大學伯克利分校教授、主席Scott Shenker撰寫的。書中作者主要分析了當前流行的各種計算框架的使用場景以及他們對應的缺點,然後談了下為什麼編寫了Spark這個框架和spark每個模塊詳細的設計理念及運行原理,這裡是做一部分摘要。
隨著現在需要處理的數據量越來越大,單機處理要向集群進行擴展,這就會帶來三個集群維度上的問題
1)並行化:多個節點同時進行數據處理
2)容錯:在多節點上處理數據,節點的故障和慢節點會變得非常常見
3)資源的動態分配:一般集群都是在多個用戶之前進行切換,所以資源的動態擴展和縮減就變得非常重要
和MapReduce對比 MapReduce做為計算引擎與Spark的區別在於:Spark RDD在並行計算階段之間能夠高效的共享數據。MapReduce計算模型中,map結果必須要從內存落到磁碟,然後reduce再將數據加載到內存中,得到的結果再次落到磁碟中;如果是多個MapReduce操作數據,那麼reduce結果數據還要再次加載到下一個map內存。正是由於數據一次次從磁碟加載到內存,所以MapReduce才會異常的慢。這也是Spark和MapReduce的區別,Spark RDD能夠將數據cache到內存中,省去了從磁碟加載的過程,同時Spark shuffle過程中的數據也是直接放在內存中的(為了避免shuffle失敗map數據丟失Spark框架還對shuffle進行了checkpoint),這就是為什麼spark比MapReduce塊的原因。Spark解決的核心問題也就是數據流模型在計算過程中高效的共享數據 。RDD具有可容錯和並行數據結構特徵,這使得用戶可以指定數據存儲到硬碟還是內存、控制數據的分區方法並在數據集上進行種類豐富的操作。
容錯 一般的框架有兩種容錯方式,提供容錯性的方法就要麼是在主機之間複製數據,要麼對各主機的更新情況做日誌記錄。
第一種容錯的方式恢復時間短但需要消耗更多的內存和磁碟空間用來存儲數據。
第二種方式不需要額外內存但是恢復時間比較長。這兩種方法對於數據密集型的任務來說代價很高,因為它們需要在帶寬遠低於內存的集群網絡間拷貝大量的數據,同時還將產生大量的存儲開銷。與上述系統不同的是,RDD提供一種基於粗粒度變換(如, map, filter, join)的接口,該接口會將相同的操作應用到多個數據集上。這使得他們可以通過記錄用來創建數據集的變換(lineage),而不需存儲真正的數據,進而達到高效的容錯性。當一個RDD的某個分區丟失的時候,RDD記錄有足夠的信息記錄其如何通過其他的RDD進行計算,且只需重新計算該分區。因此,丟失的數據可以被很快的恢復,而不需要昂貴的複製代價。
RDD RDD是一個分區的只讀記錄的集合,用戶可以控制RDD的其他兩個方面:持久化和分區。用戶可以選擇重用哪個RDD,並為其制定存儲策略(比如,內存存儲),也可以讓RDD中的數據根據記錄的key分布到集群的多個機器,這對位置優化來說是有用的,比如可用來保證兩個要Jion的數據集都使用了相同的哈希分區方式。默認情況下,Spark會將調用過persist的RDD存在內存中。但若內存不足,也可以將其寫入到硬碟上。通過指定persist函數中的參數,用戶也可以請求其他持久化策略並通過標記來進行persist,比如僅存儲到硬碟上,又或是在各機器之間複製一份。最後,用戶可以在每個RDD上設定一個持久化的優先級來指定內存中的哪些數據應該被優先寫入到磁碟。RDD的第一個優點是可以使用lineage恢復數據,不需要檢查點的開銷,此外,當出現失敗時,RDDs的分區中只有丟失的那部分需要重新計算,而且該計算可在多個節點上並發完成,不必回滾整個程序 RDD的第二個優點是,不可變性讓系統像MapReduce那樣用後備任務代替運行緩慢的任務來減少緩慢節點 (stragglers) 的影響 在RDDs上的批量操作過程中,任務的執行可以根據數據的所處的位置來進行優化,從而提高性能,其次,只要所進行的操作是只基於掃描的,當內存不足時,RDD的性能下降也是平穩的。不能載入內存的分區可以存儲在磁碟上,其性能也會與當前其他數據並行系統相當。RDDS最適合對數據集中所有的元素進行相同的操作的批處理類應用。RDDS不太適用於通過異步細粒度更新來共享狀態的應用,比如針對Web應用或增量網絡爬蟲的存儲系統
寬窄依賴 窄依賴允許在單個集群節點上流水線式執行,這個節點可以計算所有父級分區 。相反,寬依賴需要所有的父RDD數據可用並且數據已經通過類MapReduce的操作shuffle完成 其次,在窄依賴中,節點失敗後的恢復更加高效。因為只有丟失的父級分區需要重新計算,並且這些丟失的父級分區可以並行地在不同節點上重新計算。與此相反,在寬依賴的繼承關係中,單個失敗的節點可能導致一個RDD的所有先祖RDD中的一些分區丟失,導致計算的重新執行。
Spark的調度器會額外考慮被持久化(persist)的RDD的那個分區保存在內存中並可供使用,當用戶對一個RDD執行Action(如count 或save)操作時,調度器會根據該RDD的lineage,來構建一個由若干 階段(stage) 組成的一個DAG(有向無環圖)以執行程序,每個stage都包含儘可能多的連續的窄依賴型轉換。各個階段之間的分界則是寬依賴所需的shuffle操作,或者是DAG中一個經由該分區能更快到達父RDD的已計算分區。之後,調度器運行多個任務來計算各個階段所缺失的分區,直到最終得出目標RDD。調度器向各機器的任務分配採用延時調度機制並根據數據存儲位置(本地性)來確定。若一個任務需要處理的某個分區剛好存儲在某個節點的內存中,則該任務會分配給那個節點。否則,如果一個任務處理的某個分區,該分區含有的RDD提供較佳的位置(例如,一個HDFS文件),我們把該任務分配到這些位置。對應寬依賴類的操作 {比如w shuffle依賴),我們會將中間記錄物理化到保存父分區的節點上。這和MapReduce物化Map的輸出類似,能簡化數據的故障恢復過程 對於執行失敗的任務,只要它對應stage的父類信息仍然可用,它便會在其他節點上重新執行。如果某些stage變為不可用(例如,因為shuffle在map階段的某個輸出丟失了),則重新提交相應的任務以並行計算丟失的分區。(DAGscheduler官方定義) 若某個任務執行緩慢 (即"落後者"straggler),系統則會在其他節點上執行該任務的拷貝。這與MapReduce做法類似,並取最先得到的結果作為最終的結果。
Spark內存管理 Spark提供了三種對持久化RDD的存儲策略:未序列化Java對象存於內存中、序列化後的數據存於內存及磁碟存儲。第一個選項的性能表現是最優秀的,因為可以直接訪問在JAVA虛擬機內存裡的RDD對象。在空間有限的情況下,第二種方式可以讓用戶採用比JAVA對象圖更有效的內存組織方式,代價是降低了性能。第三種策略適用於RDD太大難以存儲在內存的情形,但每次重新計算該RDD會帶來額外的資源開銷。
對於有限可用內存,我們使用以RDD為對象的LRU(最近最少使用)回收算法來進行管理。當計算得到一個新的RDD分區,但卻沒有足夠空間來存儲它時,系統會從最近最少使用的RDD中回收其一個分區的空間。
除非該RDD便是新分區對應的RDD,這種情況下,Spark會將舊的分區繼續保留在內存,防止同一個RDD的分區被循環調入調出。這點很關鍵–因為大部分的操作會在一個RDD的所有分區上進行,那麼很有可能已經存在內存中的分區將會被再次使用。到目前為止,這種默認的策略在我們所有的應用中都運行很好, 當然我們也為用戶提供了「持久化優先級」選項來控制RDD的存儲。
大家可以看到,這7個概念都是Spark中最最核心的幾個概念。我們在學習過程中是萬萬繞不過去的。
模塊拆分&學習第一張圖是官方給出的Spark架構圖,我們可以看到幾個最重要的模塊:Spark Core、Spark Streaming、Spark SQL。曾經還有一個部分叫做Structured Streaming,但是這部分好像慢慢被官方拋棄了,現在Spark官方主推SQL並且基於Spark SQL進行的優化和迭代非常之多。如果你是第一次接觸Spark,並且業務沒有特殊需要,可以暫時忽略Structured Streaming。此外Spark社區在努力的像機器學習和深度學習靠攏,Spark在完成最初的流計算目標後開始發力機器學習方向,如果有興趣可以接觸這一部分的內容。
第二張圖是一個簡單的Spark快速學習的路線圖,一些基本的Linux操作和運維基礎,一點簡單的搭建虛擬機的基礎,我相信這些對大家來說都不是問題。然後我們就可以按照官網的demo進行第一次體驗了:http://spark.apache.org/examples.html
Spark的官網中給出了非常簡單的Spark入門案例,同樣我們也可以直接訪問Spark在Github的倉庫直接看更多的Demo:
https://github.com/apache/spark/tree/master/examples/src/main/java/org/apache/spark/examples
書推薦
關於Spark的書,我個人讀了應該有4-5本,每本書都沒有達到我的預期,如果說你真的需要一本書來當成工具,我覺得下面的書和Github項目可以用來參考:
第一本書是:《大數據處理框架Apache Spark設計與實現》,這本書主要是介紹Spark的設計和原理,包含一部分源碼。你可以把它當成一本八股文書來背,當然也可以當成一本指南來深入理解Spark的設計理念和深層次的原理。
這本書對應了一個Github的Repo:
https://github.com/wangzhiwubigdata/SparkInternals
還有一本電子書:http://marsishandsome.github.io/SparkSQL-Internal/
是關於Spark SQL的,這本書寫的可謂用心良苦。對SparkSQL的發展歷程和性能的優化、SparkSQL的使用方法、調優、架構、優化器Catalyst以及其他的各個模塊都有詳細介紹。
Github推薦
除了上面的推薦書對應的repo,還有一個酷玩Spark:
https://github.com/wangzhiwubigdata/CoolplaySpark
這個倉庫是由騰訊廣告部的同學發起的,主要是Spark 原始碼解析、Spark 類庫等,原始碼部分對Spark Streaming 和 Structured Streaming部分由非常深入的解釋。但是這個倉庫最後一次維護已經是2019年五月份。大家都知道2019年底Flink開源,可能搶了一部分熱度,很多公司都開始轉向對Flink的研究。
源碼閱讀Spark至今只經歷過1.x、2.x和3.x三個大版本的變化,在核心實現上,我們在Github能看到的最早的實現是0.5版本,這個版本只有1萬多行代碼,就把Spark的核心功能實現了。
當然我們不可能從這麼古老的版本看,假如你接觸過Spark,現在準備看源碼,那麼我建議從2.x版本中選取一個,最好是2.3或者2.4。但是經過如此多的迭代,Spark的代碼量已經暴增了幾倍。關於Spark3.x中的新增功能和優化例如動態資源分配,可以針對性的進行補充即可。
我把最重要的模塊列表如下:
SparkContext SparkEnv SparkConf RpcEnv SparkStatusTracker SecurityManager SparkUI MetricsSystem TaskScheduler
SerializerManager BroadcastManager ShuffleManager MemoryManager NettyBlockTransferService BlockManagerMaster BlockManager CacheManager
MemoryManager MemoryPool ExecutionMemoryPool StorageMemoryPool MemoryStore UnifiedMemoryManager
LiveListenerBus MapOutputTracker DAGScheduler TaskScheduler ExecutorAllocationManager OutputCommitCoordinator ContextClearner
LocalSparkCluster Standalone Mater/Executor/Worker的容錯
StreamingContext Receiver Dstream 窗口操作
Catalog TreeNode 詞法解析器Parser RuleExecutor Analyzer與Optimizer HiveSQL相關
假如你對圖計算Spark GraphX和機器學習Spark MLlib感興趣,可以單獨看看。
- EOF -
看完本文有收穫?請轉發分享給更多人
關注「大數據與機器學習文摘」,成為Top 1%
點讚和在看就是最大的支持❤️