- 大數據處理框架Apache Spark設計與實現
- 許利杰等
- 4786字
- 2024-01-19 16:36:17
前言
近年來,大數據憑借其數據量大、數據類型多樣、產生與處理速度快、價值高的“4V”特性成為學術界和工業界的研究熱點。由于傳統軟件難以在可接受的時間范圍內處理大數據,所以學術界和工業界研發了許多分布式的大數據系統來解決大規模數據的存儲、處理、分析和挖掘等問題。
關于Apach Spark
2003—2006年,Google在計算機系統領域會議SOSP/OSDI上發表了Google File System、MapReduce、BigTable 3篇重量級的系統論文,分別討論了大規模數據如何存儲、處理及結構化組織。之后,Apache Hadoop社區對這些論文進行了開源實現,開發了HDFS分布式文件系統、Hadoop MapReduce大數據處理框架和HBase分布式Key-Value數據庫,大大降低了大數據應用開發、運行及數據存儲管理的難度。這些系統被廣泛應用于互聯網、電信、金融、科研等領域,以進行大規模數據存儲與處理。
對于大數據處理框架來說,MapReduce成功地將函數式編程思想引入分布式數據處理中,僅僅用兩個函數(map()和reduce())就解決了一大類的大數據處理問題,而且不要求用戶熟悉分布式文件系統。然而,隨著大數據應用越來越多,處理性能的要求越來越高,MapReduce的一些缺點也顯現出來。例如,MapReduce編程模型的表達能力較弱,僅使用map()和reduce()兩個函數難以實現復雜的數據操作;處理流程固定,不容易實現迭代計算;基于磁盤進行數據傳遞,效率較低。這些缺點導致使用MapReduce開發效率較低、執行復雜的數據處理任務的性能也不高。
為了解決這些問題,微軟在2008—2009年研發了Dryad/DryadLINQ,其中Dryad類似MapReduce,但以有向無環圖(Directed Acycline Graph,DAG)形式的數據流取代了MapReduce固定的map-reduce 兩階段數據流,處理流程更通用,支持復雜的數據處理任務。DryadLINQ為Dryad提供了高層編程語言,將更多的函數式編程思想(來源于C#的LINQ)引入編程模型中,表達能力更強,如容易實現join()等操作。然而,由于Dryad/DryadLINQ在當時沒有開源,所以沒有得到大規模使用。
鑒于MapReduce、Dryad等框架存在一些問題,2012年,UC Berkeley的AMPLab研發并開源了新的大數據處理框架Spark。其核心思想包括兩方面:一方面對大數據處理框架的輸入/輸出、中間數據進行建模,將這些數據抽象為統一的數據結構,命名為彈性分布式數據集(Resilient Distributed Dataset,RDD),并在此數據結構上構建了一系列通用的數據操作,使得用戶可以簡單地實現復雜的數據處理流程;另一方面采用基于內存的數據聚合、數據緩存等機制來加速應用執行,尤其適用于迭代和交互式應用。Spark采用EPFL大學研發的函數式編程語言Scala實現,并且提供了Scala、Java、Python、R四種語言的接口,以方便開發者使用熟悉的語言進行大數據應用開發。
經過多年的發展,Spark也與Hadoop一樣構建了完整的生態系統。Apache Spark生態系統以Spark處理框架為核心,在上層構建了面向SQL語言的Spark SQL框架、面向大規模圖計算的GraphX框架、面向大規模機器學習的MLlib框架及算法庫,以及面向流處理的Spark Streaming框架;在下層,Spark及其關聯社區也推出了相關存儲系統,如基于內存的分布式文件系統Alluxio、支持ACID 事務的數據湖系統Delta Lake等。由于整個Spark生態系統中包含的系統和框架眾多,本書主要關注生態系統中核心的Spark處理框架本身。下面介紹本書的一些基本信息。
本書的寫作目的及面向的讀者
本書的寫作目的是以Spark框架為核心,總結大數據處理框架的設計和實現原理,包括框架設計中面臨的基本問題、可能的解決方案、Spark采用的方案、具體實現方法,以及優缺點等。與機器學習等領域有成熟的理論模型不同,大數據處理框架并沒有一個完整的理論模型,但是具有一些系統設計模型及設計方案,如編程模型、邏輯處理流程、物理執行計劃及并行化方案等。這些模型及方案是研究人員和工程師在實踐中經過不斷探索和改進得到的實踐經驗。本書的目的是將這些寶貴經驗抽象總結為系統設計模型和方案,幫助讀者從理論層和實現層深入理解大數據處理框架,具體體現如下。
(1)幫助讀者理解Spark應用,以及與Spark關聯的上下層框架。Spark等大數據處理框架只將數據接口和操作接口暴露給用戶,用戶一般不了解應用程序是如何被轉化為可分布執行任務的,以及任務是如何執行的。本書詳細總結了Spark框架將應用程序轉化為邏輯處理流程,并進一步轉化為物理執行計劃的一般過程。理解這個過程將幫助讀者理解更復雜的Spark應用,如在第5章中介紹的迭代型機器學習應用和圖計算應用。同時,理解Spark的設計與實現原理也有助于理解Spark生態圈中的上下層框架之間的關系,如Spark SQL、MLlib、GraphX是如何利用Spark框架來執行SQL、機器學習和圖計算任務的。
(2)幫助讀者開發性能更好、可靠性更高的大數據應用。用戶在運行大數據應用時,經常面臨應用執行效率低下、無響應、I/O異常、內存溢出等性能和可靠性問題。本書講述了與Spark框架性能和可靠性相關的Shuffle機制、數據緩存機制、錯誤容忍機制、內存管理機制等。理解Spark應用性能和可靠性的影響因素,幫助讀者在運行Spark應用時進行參數調優,有助于更好地利用數據緩存來提升應用性能,同時合理利用數據持久化機制來減少執行錯誤、內存溢出等可靠性問題。
(3)幫助讀者對Spark等大數據框架進行進一步優化和改進。在實際使用大數據處理框架的過程中,開發者經常會因為軟硬件環境、數據特征、應用邏輯、執行性能的特殊需求,需要對Spark框架的部分功能進行優化改進。例如,在內存較小的集群上運行需要對內存管理進行改進,經常出現網絡阻塞時需要對Shuffle機制進行改進,針對一些特殊應用需要開發新的數據操作等。要對Spark框架進行改進,不僅需要非常了解Spark框架的設計和實現原理,還需要清楚改進后可能出現的正確性和可靠性問題。本書對Spark設計和實現過程中的問題挑戰、解決方案、優缺點的闡述將幫助開發者和研究人員對框架進行優化改進。
因此,我們相信,本書對于大數據處理框架的用戶、開發者和研究人員都會有一定的幫助。
本書的主要內容
本書主要介紹Apache Spark大數據處理框架的設計和實現原理,附帶討論與Hadoop MapReduce等框架的優缺點對比。全書分9章,主要包含以下四部分內容。
第一部分 大數據處理框架的基礎知識。第1章介紹大數據處理框架的基本概念、系統架構,以及與其相關的研究工作。第2章概覽Spark的系統架構、編程模型,并以一個典型的Spark應用為例概述Spark應用的執行流程。Spark初學者可以直接從第2章開始閱讀。
第二部分 Spark大數據處理框架的核心理論。該部分包括兩章,主要介紹Spark如何將應用程序轉化為可以分布執行的計算任務。其中,第3章介紹Spark將應用程序轉化為邏輯處理流程的一般過程及方法,并對常用的數據操作進行詳細分析。第4章討論Spark將邏輯處理流程轉化為物理執行計劃的一般過程及方法,以及常用的數據操作形成的計算任務。
第三部分 典型的Spark應用。第5章介紹復雜的迭代型Spark應用,包括迭代型機器學習應用和圖計算應用,以及這些應用的并行化方法。這些應用也進一步驗證了Spark框架的通用性。
第四部分 大數據處理框架性能和可靠性保障機制。該部分主要探究Spark框架性能和可靠性相關的技術,其中包括第6章的Shuffle機制、第7章的數據緩存機制、第8章的錯誤容忍機制及第9章的內存管理機制。
本書特點
本書注重設計原理和實現方案的闡述,寫作方式考慮了技術深度、研究價值、易讀性等因素,具體特點如下。
(1)采用問題驅動的闡述方式。本書在章節開頭或者中間引入Spark設計和實現過程中面臨的挑戰性問題(Problems),然后將這些問題拆分為子問題逐步深入討論可能的解決方案(Potential Solutions),最后介紹為什么Spark會使用當前的解決方案(Why)及具體是如何實現的(How)。這種表述方式可以讓讀者“知其然”,并且“知其所以然”,也就是讓讀者既從使用者角度又從設計者角度來理解大數據處理框架中的基本問題、基本設計方法及實現思想。
(2)強調基本原理的闡述。本書著重介紹Spark設計和實現的基本原理,不具體展示代碼實現的細節。這樣做的第一個原因是,其基本原理是對代碼的高層抽象,對大數據框架的用戶、開發者和研究人員來說,原理更重要、更容易理解。第二個原因是,代碼在不斷優化更新,而基本原理比較穩定。本書也可以看作從Spark代碼中抽象出概要設計和詳細設計。
(3)圖文并茂,容易理解。本書將復雜的設計和實現邏輯抽象為圖例,并通過文字描述和實例來方便讀者理解復雜的設計方案和執行過程。對于一些復雜的問題,本書還進行了分類討論,使技術內容更具有邏輯性、更容易被理解。
(4)具有一定的學術研究價值。本書討論了Spark設計與實現過程中存在的一些挑戰性問題及當前解決方案的不足,同時也探討了一些相關的研究工作,并在必要時與Hadoop進行了對比。這些討論將有助于讀者研究和優化改進大數據處理框架。
Spark版本與API問題
本書以Spark 2.4.3版和RDD API為基礎進行編寫。實際上,從Spark 2.0版到未來的Spark 3.0版,Spark社區推薦用戶使用DataSet、DataFrame等面向結構化數據的高層API (Structured API)來替代底層的RDD API,因為這些高層API包含更多的數據類型信息(Schema),支持SQL操作,并且可以利用經過高度優化的Spark SQL引擎來執行。然而,由于以下幾個原因,本書使用RDD API來探討Spark的設計原理和實現。
(1)RDD API更基礎,更適合分析大數據處理框架中的一些基本問題和原理。相比DataSet、DataFrame數據結構,RDD API的數據結構更簡單和通用,更適合用來展示一些基本概念和原理,如數據分區方法、每個數據操作的執行過程(生成什么樣的RDD API、建立什么樣的數據依賴關系),以及執行階段劃分方法、任務劃分方法等。而且,RDD API包含更多的數據操作類型,可以用來展示更豐富的數據依賴關系、邏輯處理流程等。
(2)學習RDD API及其執行原理,幫助讀者理解高層API和Spark SQL執行引擎。由于Spark SQL執行引擎采用了許多數據庫、分布式系統、編譯等領域的優化技術,其將應用程序(使用DataSet/DataFrame API編寫)轉化為物理執行計劃的過程比較復雜。本書講解了“RDD API應用程序-邏輯處理流程-物理執行計劃”的基本轉化過程,幫助讀者進一步學習和理解更復雜的Spark SQL轉化過程。讀者可以參閱Bill Chambers和Matei Zaharia合著的Spark:The Definitive Guide,學習DataSet、DataFrame API的具體使用方法,也可以參閱朱鋒、張韶全、黃明合著的《Spark SQL內核剖析》,進一步學習Spark SQL引擎的執行過程和具體實現。
(3)上層框架(如MLlib、GraphX)中有很多代碼使用RDD API,學習原生的RDD API有助于在分布式層面理解數據和計算的抽象表達,也有助于理解圖計算應用和機器學習應用中的數據分區(如邊劃分、點劃分),以及計算任務劃分方法(如數據并行等)。
另外,在未來的Spark 3.0版本中還會有一些新的特性,如支持GPU調度、SQL自適應查詢執行等。如果有機會,我們會在本書的下一版中探討更多關于Spark SQL執行引擎的設計原理,以及這些新特性。
與SparkInternals技術文檔的關系
有些讀者可能看過我們在2015年撰寫并在GitHub上公開的SparkInternals技術文檔。該文檔介紹了Spark 1.0與Spark 2.0版本的設計原理和實現,迄今已收到4000多顆stars、1500次forks,也被翻譯為英文、日文和泰文,受到很多大數據工程師和研究人員的關注。
不過,SparkInternals技術文檔中總結的設計原理不夠完整和深入,而且后幾章中涉及的實現細節也較多(包含一些實現細節代碼)。由于這本書的目的是總結設計原理和實現,所以并沒有使用太多SparkInternals技術文檔中的內容,而是按照“問題-解決方案-Spark采用的方案-實現-優缺點”的邏輯重新撰寫了相關章節,只是使用了SparkInternals技術文檔中的部分圖例。當然,如果讀者想要了解一些實現細節和代碼,也可將SparkInternals技術文檔作為本書的補充資料。
我們在GitHub上建立了一個名為ApacheSparkBook的公開項目,將本書設計的示例代碼和高清圖片放到了項目中(項目地址為https://github.com/JerryLead/ApacheSparkBook)。讀者可以在項目中進行提問,方便我們解答問題或勘誤。
由于作者水平和經驗有限,本書的錯漏和不足之處歡迎廣大讀者朋友批評指正,可以將意見提交到GitHub項目中或者通過電子郵件(csxulijie@gmail.com)聯系作者。
在本書寫作過程中,作者得到了所在單位(中國科學院軟件研究所)諸多老師的關注和支持,在此感謝魏峻、武延軍、王偉等老師提供的科研工作環境。作者的研究工作受到國家自然科學基金(61802377),以及中國科學院青年創新促進會的項目支持。
感謝參與本書初稿討論和審閱的各位朋友,包括亞馬遜的紀樹平博士、騰訊的朱鋒博士、阿里巴巴的沈雯婷、中國科學院軟件研究所的李慧、王棟、葉星彤、康鍇等同學,以及Databricks的Xiao Li博士及其團隊。同時,也感謝廣大讀者對GitHub上SparkInternals技術文檔的支持和反饋意見。
電子工業出版社的孫學瑛編輯及其團隊在本書的審校、排版、出版發行過程中付出了巨大努力,在此表示由衷感謝!
最后,感謝家人及朋友對作者一如既往的支持。