Spark設計理念與基本架構

沒心沒肺 8年前發布 | 56K 次閱讀 Spark 分布式/云計算/大數據

來自: http://www.cnblogs.com/jiaan-geng/p/5159883.html

《深入理解Spark:核心思想與源碼分析》一書前言的內容請看鏈接 《深入理解SPARK:核心思想與源碼分析》一書正式出版上市

《深入理解Spark:核心思想與源碼分析》一書第一章的內容請看鏈接《第1章 環境準備》

本文主要展示本書的第2章內容:

Spark設計理念與基本架構

“若夫乘天地之正,而御六氣之辯,以游無窮者,彼且惡乎待哉?”

—— 《莊子·逍遙游》

n   本章導讀:

上一章,介紹了 Spark 環境的搭建,為方便讀者學習 Spark 做好準備。本章首先從 Spark 產生的背景開始,介紹 Spark 的主要特點、基本概念、版本變遷。然后簡要說明 Spark 的主要模塊和編程模型。最后從 Spark 的設計理念和基本架構入手,使讀者能夠對 Spark 有宏觀的認識,為之后的內容做一些準備工作。

Spark 是一個通用的并行計算框架,由加州伯克利大學( UCBerkeley )的 AMP 實驗室開發于 2009 年,并于 2010 年開源。 2013 年成長為 Apache 旗下為大數據領域最活躍的開源項目之一。 Spark 也是基于 map reduce 算法模式實現的分布式計算框架,擁有 Hadoop MapReduce 所具有的優點,并且解決了 Hadoop MapReduce 中的諸多缺陷。

2.1 初識 Spark

2.1.1 Hadoop MRv1 的局限

早在 Hadoop1.0 版本,當時采用的是 MRv1 版本的 MapReduce 編程模型。 MRv1 版本的實現都封裝在 org.apache.hadoop.mapred 包中, MRv1 的 Map 和 Reduce 是通過接口實現的。 MRv1 包括三個部分:

q   運行時環境( JobTracker 和 TaskTracker );

q   編程模型( MapReduce );

q   數據處理引擎( Map 任務和 Reduce 任務)。

MRv1 存在以下不足:

q   可擴展性差:在運行時, JobTracker 既負責資源管理又負責任務調度,當集群繁忙時, JobTracker 很容易成為瓶頸,最終導致它的可擴展性問題。

q   可用性差:采用了單節點的 Master ,沒有備用 Master 及選舉操作,這導致一旦 Master 出現故障,整個集群將不可用。

q   資源利用率低: 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 也會被閑置。

q   不能支持多種 MapReduce 框架:無法通過可插拔方式將自身的 MapReduce 框架替換為其他實現,如 Spark 、 Storm 等。

MRv1 的示意如圖 2-1 。

2-1        MRv1 示意圖 [1]

Apache 為了解決以上問題,對 Hadoop 升級改造, MRv2 最終誕生了。 MRv2 中,重用了 MRv1 中的編程模型和數據處理引擎。但是運行時環境被重構了。 JobTracker 被拆分成了通用的資源調度平臺( ResourceManager ,簡稱 RM )和負責各個計算框架的任務調度模型( ApplicationMaste ,簡稱 AM )。 MRv2 中 MapReduce 的核心不再是 MapReduce 框架,而是 YARN 。在以 YARN 為核心的 MRv2 中, MapReduce 框架是可插拔的,完全可以替換為其他 MapReduce 實現,比如 Spark 、 Storm 等。 MRv2 的示意如圖 2-2 所示。

2-2        MRv2 示意圖

Hadoop MRv2 雖然解決了 MRv1 中的一些問題,但是由于對 HDFS 的頻繁操作(包括計算結果持久化、數據備份及 shuffle 等)導致磁盤 I/O 成為系統性能的瓶頸,因此只適用于離線數據處理,而不能提供實時數據處理能力。

2.1.2 Spark 使用場景

Hadoop 常用于解決高吞吐、批量處理的業務場景,例如離線計算結果用于瀏覽量統計。如果需要實時查看瀏覽量統計信息, Hadoop 顯然不符合這樣的要求。 Spark 通過內存計算能力極大地提高了大數據處理速度,滿足了以上場景的需要。此外, Spark 還支持 SQL 查詢,流式計算,圖計算,機器學習等。通過對 Java 、 Python 、 Scala 、 R 等語言的支持,極大地方便了用戶的使用。

2.1.3 Spark 的特點

Spark 看到 MRv1 的問題,對 MapReduce 做了大量優化,總結如下:

q   快速處理能力。隨著實時大數據應用越來越多, Hadoop 作為離線的高吞吐、低響應框架已不能滿足這類需求。 Hadoop MapReduce 的 Job 將中間輸出和結果存儲在 HDFS 中,讀寫 HDFS 造成磁盤 IO 成為瓶頸。 Spark 允許將 中間輸出和結果存儲在內存中,節省了大量的磁盤 IO 。同時 Spark 自身的 DAG 執行引擎也支持數據在內存中的計算。 Spark 官網聲稱性能比 Hadoop 快 100 倍,如圖 2-3 所示。即便是內存不足需要磁盤 IO ,其速度也是 Hadoop 的 10 倍以上。

2-3        Hadoop 與 Spark 執行邏輯回歸時間比較

q   易于使用。 Spark 現在支持 Java 、 Scala 、 Python 和 R 等語言編寫應用程序,大大降低了使用者的門檻。自帶了 80 多個高等級操作符,允許在 Scala , Python , R 的 shell 中進行交互式查詢。

q   支持查詢。 Spark 支持 SQL 及 Hive SQL 對數據查詢。

q   支持流式計算。與 MapReduce 只能處理離線數據相比, Spark 還支持實時的流計算。 Spark 依賴 Spark Streaming 對數據進行實時的處理,其流式處理能力還要強于 Storm 。

q   可用性高。 Spark 自身實現了 Standalone 部署模式,此模式下的 Master 可以有多個,解決了單點故障問題。此模式完全可以使用其他集群管理器替換,比如 YARN 、 Mesos 、 EC2 等。

q   豐富的數據源支持。 Spark 除了可以訪問操作系統自身的文件系統和 HDFS ,還可以訪問 Cassandra, HBase, Hive, Tachyon 以及任何 Hadoop 的數據源。這極大地方便了已經使用 HDFS 、 Hbase 的用戶順利遷移到 Spark 。

2.2 Spark 基礎知識

1.版本變遷

經過 4 年多的發展, Spark 目前的版本是 1.4.1 。我們簡單看看它的版本發展過程。

1)          Spark 誕生于 UCBerkeley 的 AMP 實驗室( 2009 )。

2)          Spark 正式對外開源( 2010 )。

3)          Spark 0.6.0 版本發布( 2012-10-15 ),大范圍的性能改進,增加了一些新特性,并對 Standalone 部署模式進行了簡化。

4)          Spark 0.6.2 版本發布( 2013-02-07 ),解決了一些 bug ,并增強了系統的可用性。

5)          Spark 0.7.0 版本發布( 2013-02-27 ),增加了更多關鍵特性,例如: Python API 、 Spark Streaming 的 alpha 版本等。

6)          Spark 0.7.2 版本發布( 2013-06-02 ),性能改進并解決了一些 bug ,新的 API 使用的例子。

7)          Spark 接受進入 Apache 孵化器( 2013-06-21 )。

8)          Spark 0.7.3 版本發布( 2013-07-16 ),一些 bug 的解決,更新 Spark Streaming API 等。

9)          Spark 0.8.0 版本發布( 2013-09-25 ),一些新功能及可用性改進。

10)      Spark 0.8.1 版本發布( 2013-12-19 ),支持 Scala 2.9 , YARN 2.2 , Standalone 部署模式下調度的高可用性, shuffle 的優化等。

11)      Spark 0.9.0 版本發布( 2014-02-02 ),增加了 GraphX ,機器學習新特性,流式計算新特性,核心引擎優化(外部聚合、加強對 YARN 的支持)等。

12)      Spark 0.9.1 版本發布( 2014-04-09 ),增加使用 YARN 的穩定性,改進 Scala 和 Python API 的奇偶性。

13)      Spark 1.0.0 版本發布( 2014-05-30 ),增加了 Spark SQL 、 MLlib 、 GraphX 和 Spark Streaming 都增加了新特性并進行了優化。 Spark 核心引擎還增加了對安全 YARN 集群的支持。

14)      Spark 1.0.1 版本發布( 2014-07-11 ),增加了 Spark SQL 的新特性和堆 JSON 數據的支持等。

15)      Spark 1.0.2 版本發布( 2014-08-05 ), Spark 核心 API 及 Streaming , Python , MLlib 的 bug 修復。

16)      Spark 1.1.0 版本發布( 2014-09-11 )。

17)      Spark 1.1.1 版本發布( 2014-11-26 ), Spark 核心 API 及 Streaming , Python , SQL , GraphX 和 MLlib 的 bug 修復。

18)      Spark 1.2.0 版本發布( 2014-12-18 )。

19)      Spark 1.2.1 版本發布( 2015-02-09 ), Spark 核心 API 及 Streaming , Python , SQL , GraphX 和 MLlib 的 bug 修復。

20)      Spark 1.3.0 版本發布( 2015-03-13 )。

21)      Spark 1.4.0 版本發布( 2015-06-11 )。

22)      Spark 1.4.1 版本發布( 2015-07-15 ), DataFrame API 及 Streaming , Python , SQL 和 MLlib 的 bug 修復。

2.基本概念

要想對 Spark 有整體性的 了解 ,推薦讀者閱讀 Matei Zaharia 的 Spark 論文。此處筆者先介紹 Spark 中的一些概念:

q   RDD ( resillient distributed dataset ):彈性分布式數據集。

q   Task :具體執行任務。 Task 分為 ShuffleMapTask 和 ResultTask 兩種。 ShuffleMapTask 和 ResultTask 分別類似于 Hadoop 中的 Map , Reduce 。

q   Job :用戶提交的作業。一個 Job 可能由一到多個 Task 組成。

q   Stage : Job 分成的階段。一個 Job 可能被劃分為一到多個 Stage 。

q   Partition :數據分區。即一個 RDD 的數據可以劃分為多少個分區。

q   NarrowDependency :窄依賴。即子 RDD 依賴于父 RDD 中固定的 Partition 。 NarrowDependency 分為 OneToOneDependency 和 RangeDependency 兩種。

q   ShuffleDependency : shuffle 依賴,也稱為寬依賴。即子 RDD 對父 RDD 中的所有 Partition 都有依賴。

q   DAG ( Directed Acycle graph ):有向無環圖。用于反映各 RDD 之間的依賴關系。

3. Scala 與 Java 的比較

Spark 為什么要選擇 Java 作為開發語言?筆者不得而知。如果能對二者進行比較,也許能看出一些端倪。表 2-1 列出了對 Scala 與 Java 的比較。

2-1        Scala 與 Java 的比較

Scala

Java

語言類型

面向函數為主,兼有面向對象

面向對象( Java8 也增加了 lambda 函數編程)

簡潔性

非常簡潔

不簡潔

類型推斷

豐富的類型推斷,例如深度和鏈式的類型推斷、 duck type 、隱式類型轉換等,但也因此增加了編譯時長

少量的類型推斷

可讀性

一般,豐富的語法糖導致的各種奇幻用法,例如方法簽名

學習成本

較高

一般

語言特性

非常豐富的語法糖和更現代的語言特性,例如 Option 、模式匹配、使用空格的方法調用

豐富

并發編程

使用 Actor 的消息模型

使用阻塞、鎖、阻塞隊列等

通過以上比較似乎仍然無法判斷 Spark 選擇開發語言的原因。由于函數式編程更接近計算機思維,因此便于通過算法從大數據中建模,這應該更符合 Spark 作為大數據框架的理念吧!

2.3 Spark 基本設計思想

2.3.1 模塊設計

整個 Spark 主要由以下模塊組成:

q   Spark Core : Spark 的核心功能實現,包括: SparkContext 的初始化( Driver Application 通過 SparkContext 提交)、部署模式、存儲體系、任務提交與執行、計算引擎等。

q   Spark SQL :提供 SQL 處理能力,便于熟悉關系型數據庫操作的工程師進行交互查詢。此外,還為熟悉 Hadoop 的用戶提供 Hive SQL 處理能力。

q   Spark Streaming :提供流式計算處理能力,目前支持 Kafka 、 Flume 、 推ter 、 MQTT 、 ZeroMQ 、 Kinesis 和簡單的 TCP 套接字等數據源。此外,還提供窗口操作。

q   GraphX :提供圖計算處理能力,支持分布式, Pregel 提供的 API 可以解決圖計算中的常見問題。

q   MLlib :提供機器學習相關的統計、分類、回歸等領域的多種算法實現。其一致的 API 接口大大降低了用戶的學習成本。

Spark SQL 、 Spark Streaming 、 GraphX 、 MLlib 的能力都是建立在核心引擎之上,如圖 2-4 。

2-4        Spark 各模塊依賴關系

1.    Spark 核心功能

Spark Core 提供 Spark 最基礎與最核心的功能,主要包括:

q   SparkContext :通常而言, Driver Application 的執行與輸出都是通過 SparkContext 來完成的,在正式提交 Application 之前,首先需要初始化 SparkContext 。 SparkContext 隱藏了網絡通信、分布式部署、消息通信、存儲能力、計算能力、緩存、測量系統、文件服務、 Web 服務等內容,應用程序開發者只需要使用 SparkContext 提供的 API 完成功能開發。 SparkContext 內置的 DAGScheduler 負責創建 Job ,將 DAG 中的 RDD 劃分到不同的 Stage ,提交 Stage 等功能。內置的 TaskScheduler 負責資源的申請、任務的提交及請求集群對任務的調度等工作。

q   存儲體系: Spark 優先考慮使用各節點的內存作為存儲,當內存不足時才會考慮使用磁盤,這極大地減少了磁盤 I/O ,提升了任務執行的效率,使得 Spark 適用于實時計算、流式計算等場景。此外, Spark 還提供了以內存為中心的高容錯的分布式文件系統 Tachyon 供用戶進行選擇。 Tachyon 能夠為 Spark 提供可靠的內存級的文件共享服務。

q   計算引擎:計算引擎由 SparkContext 中的 DAGScheduler 、 RDD 以及具體節點上的 Executor 負責執行的 Map 和 Reduce 任務組成。 DAGScheduler 和 RDD 雖然位于 SparkContext 內部,但是在任務正式提交與執行之前將 Job 中的 RDD 組織成有向無關圖(簡稱 DAG )、并對 Stage 進行劃分決定了任務執行階段任務的數量、迭代計算、 shuffle 等過程。

2.    Spark 擴展功能

為了擴大應用范圍, Spark 陸續增加了一些擴展功能,主要包括:

q   Spark SQL :由于 SQL 具有普及率高、學習成本低等特點,為了擴大 Spark 的應用面,因此增加了對 SQL 及 Hive 的支持。 Spark SQL 的過程可以總結為:首先使用 SQL 語句解析器( SqlParser )將 SQL 轉換為語法樹( Tree ),并且使用規則執行器( RuleExecutor )將一系列規則( Rule )應用到語法樹,最終生成物理執行計劃并執行的過程。其中,規則包括語法分析器( Analyzer )和優化器( Optimizer )。 Hive 的執行過程與 SQ 類似。

q   Spark Streaming : Spark Streaming 與 Apache Storm 類似,也用于流式計算。 Spark Streaming 支持 Kafka 、 Flume 、 推ter 、 MQTT 、 ZeroMQ 、 Kinesis 和簡單的 TCP 套接字等多種數據輸入源。輸入流接收器( Receiver )負責接入數據,是接入數據流的接口規范。 Dstream 是 Spark Streaming 中所有數據流的抽象, Dstream 可以被組織為 DStream Graph 。 Dstream 本質上由一系列連續的 RDD 組成。

q   GraphX : Spark 提供的分布式圖計算框架。 GraphX 主要遵循整體同步并行計算模式( Bulk Synchronous Parallell ,簡稱 BSP )下的 Pregel 模型實現。 GraphX 提供了對圖的抽象 Graph , Graph 由頂點( Vertex )、邊( Edge )及繼承了 Edge 的 EdgeTriplet (添加了 srcAttr 和 dstAttr 用來保存源頂點和目的頂點的屬性)三種結構組成。 GraphX 目前已經封裝了最短路徑、網頁排名、連接組件、三角關系統計等算法的實現,用戶可以選擇使用。

q   MLlib : Spark 提供的 機器學習框架。機器學習是一門涉及概率論、統計學、逼近論、凸分析、算法復雜度理論等多領域的交叉學科。 MLlib 目前已經提供了基礎統計、分類、回歸、決策樹、隨機森林、樸素貝葉斯、保序回歸、 協同過濾、聚類、維數縮減、特征提取與轉型、頻繁模式挖掘、預言模型標記語言、管道等多種數理統計、概率論、數據挖掘方面的數學算法 。

2.3.2  Spark 模型設計

1. Spark 編程模型

Spark 應用程序從編寫到提交、執行、輸出的整個過程如圖 2-5 所示,圖中描述的步驟如下:

1)          用戶使用 SparkContext 提供的 API (常用的有 textFile 、 sequenceFile 、 runJob 、 stop 等)編寫 Driver application 程序。此外 SQLContext 、 HiveContext 及 StreamingContext 對 SparkContext 進行封裝,并提供了 SQL 、 Hive 及流式計算相關的 API 。

2)          使用 SparkContext 提交的用戶應用程序,首先會使用 BlockManager 和 BroadcastManager 將任務的 Hadoop 配置進行廣播。然后由 DAGScheduler 將任務轉換為 RDD 并組織成 DAG , DAG 還將被劃分為不同的 Stage 。最后由 TaskScheduler 借助 ActorSystem 將任務提交給集群管理器( Cluster Manager )。

3)          集群管理器( Cluster Manager )給任務分配資源,即將具體任務分配到 Worker 上, Worker 創建 Executor 來處理任務的運行。 Standalone 、 YARN 、 Mesos 、 EC2 等都可以作為 Spark 的集群管理器。

2-5        代碼執行過程

2. Spark 計算模型

RDD 可以看做是對各種數據計算模型的統一抽象, Spark 的計算過程主要是 RDD 的迭代計算過程,如圖 2-6 。 RDD 的迭代計算過程非常類似于管道。分區數量取決于 partition 數量的設定,每個分區的數據只會在一個 Task 中計算。所有分區可以在多個機器節點的 Executor 上并行執行。

2-6        RDD 計算模型

2.4 Spark 基本架構

從集群部署的角度來看, Spark 集群由以下部分組成:

q   Cluster Manager : Spark 的集群管理器,主要 負責資源的分配與管理。 集群管理器分配的資源屬于一級分配,它將各個 Worker 上的內存、 CPU 等資源分配給應用程序,但是并不負責對 Executor 的資源分配。 目前, Standalone 、 YARN 、 Mesos 、 EC2 等都可以作為 Spark 的集群管理器。

q   Worker : Spark 的工作節點。對 Spark 應用程序來說,由集群管理器分配得到資源的 Worker 節點主要負責以下工作:創建 Executor ,將資源和任務進一步分配給 Executor ,同步資源信息給 Cluster Manager 。

q   Executor :執行計算任務的一線進程。主要負責任務的執行以及與 Worker 、 Driver App 的信息同步。

q   Driver App :客戶端驅動程序,也可以理解為客戶端應用程序,用于將任務程序轉換為 RDD 和 DAG ,并與 Cluster Manager 進行通信與調度。

這些組成部分之間的整體關系如圖 2-7 所示。

2-7        Spark 基本架構圖

2.5  小結

每項技術的誕生都會由某種社會需求所驅動, Spark 正是在實時計算的大量需求下誕生的。 Spark 借助其優秀的處理能力,可用性高,豐富的數據源支持等特點,在當前大數據領域變得火熱,參與的開發者也越來越多。 Spark 經過幾年的迭代發展,如今已經提供了豐富的功能。筆者相信, Spark 在未來必將產生更耀眼的火花。

[1] 2-1 和圖 2-2 都來源自 http://blog.chinaunix.net/uid-28311809-id-4383551.html

后記:自己犧牲了7個月的周末和下班空閑時間,通過研究Spark源碼和原理,總結整理的《深入理解Spark:核心思想與源碼分析》一書現在已經正式出版上市,目前亞馬遜、京東、當當、天貓等網站均有銷售,歡迎感興趣的同學購買。我開始研究源碼時的Spark版本是1.2.0,經過7個多月的研究和出版社近4個月的流程,Spark自身的版本迭代也很快,如今最新已經是1.6.0。目前市面上另外2本源碼研究的Spark書籍的版本分別是0.9.0版本和1.2.0版本,看來這些書的作者都與我一樣,遇到了這種問題。由于研究和出版都需要時間,所以不能及時跟上Spark的腳步,還請大家見諒。但是Spark核心部分的變化相對還是很少的,如果對版本不是過于追求,依然可以選擇本書。

京東(現有滿100減30活動): http://item.jd.com/11846120.html

當當: http://product.dangdang.com/23838168.html

亞馬遜: http://www.amazon.cn/gp/product/B01A5G5LHK/sr=8-1/qid=1452505597/ref=olp_product_details?ie=UTF8&me=&qid=1452505597&sr=8-1

</div> </div>

 本文由用戶 沒心沒肺 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!