聲明:
本文轉(zhuǎn)自我的個(gè)人博客,有興趣的可以查看原文。
轉(zhuǎn)發(fā)請(qǐng)注明來(lái)源。
最近工作開(kāi)始接觸Spark,本系列博客可以作為學(xué)習(xí)思考的紀(jì)錄。
如果無(wú)特殊說(shuō)明,均針對(duì)Spark 2.2 。
1. Spark 介紹
1.1 Spark 是什么
Apache Spark is a fast and general engine for large-scale data processing.
Spark 官網(wǎng)將Spark 定義為一個(gè)大型可擴(kuò)展數(shù)據(jù)的快速和通用處理引擎。
首先,Spark 采用了先進(jìn)的DAG執(zhí)行引擎,支持循環(huán)數(shù)據(jù)流和內(nèi)存計(jì)算,使得 Spark 速度更快,在內(nèi)存中的速度是Hadoop MR的百倍,在磁盤(pán)上的速度是Hadoop MR的十倍(官網(wǎng)數(shù)據(jù)) 。
其次,Spark 是一個(gè)通用的處理引擎。Spark 被設(shè)計(jì)用來(lái)做批處理、迭代運(yùn)算、交互式查詢、流處理、機(jī)器學(xué)習(xí)等。
另外,Spark 易用,可以用Scala、Java、Python、R等快速開(kāi)發(fā)分布式應(yīng)用,Spark 提供了大量的高級(jí)API,方便開(kāi)發(fā)(對(duì)比MapReduce...)。
最后,Spark 集成了多種數(shù)據(jù)源,并且可以通過(guò)Yarn、Mesos、Standalone(Spark 提供的部署方式)等各種模式運(yùn)行。
1.2 為什么需要Spark
在Spark 之前,我們已經(jīng)有了Hadoop,Hadoop 作為大數(shù)據(jù)時(shí)代企業(yè)首選技術(shù),方興未艾,我們?yōu)槭裁催€需要Spark 呢?
我的理解是,Hadoop 對(duì)某些工作并不是最優(yōu)的選擇:
- 中間輸出到磁盤(pán),會(huì)產(chǎn)生較高的延遲。
- 缺少對(duì)迭代運(yùn)算的支持。
總的來(lái)說(shuō),Hadoop 設(shè)計(jì)得比較適合處理離線數(shù)據(jù),在實(shí)時(shí)查詢、迭代計(jì)算方面存在不足,而業(yè)界對(duì)實(shí)時(shí)查詢和迭代計(jì)算有著越來(lái)越多的需求。Spark 的出現(xiàn)正好能解決這些問(wèn)題,快速、易用、通用,而且對(duì)有效支持Hadoop。
1.3 Spark 核心生態(tài)圈與重要擴(kuò)展

上圖是一個(gè)比較常見(jiàn)的以 Spark 為核心的大數(shù)據(jù)處理框架。
其中,Spark Core 提供了 Spark 中的任務(wù)調(diào)度、內(nèi)存管理、錯(cuò)誤恢復(fù)、與存儲(chǔ)系統(tǒng)交互等基本功能,而且,Spark Core 定義了RDDs(resilient distributed datasets,彈性分布式數(shù)據(jù)集,是Spark 的核心抽象)和操作RDDs的各種APIs。
基于Spark Core,提供六大核心擴(kuò)展。Spark SQL 提供交互式SQL查詢功能;Spark 2.0 引入了 Structured Streaming,Structured Streaming 是建立在Spark SQL 之上的可擴(kuò)展、高容錯(cuò)的流處理引擎;MLlib 提供機(jī)器學(xué)習(xí);GraphX提供圖計(jì)算服務(wù);Spark Streaming 基于 Spark 核心 API 提供可擴(kuò)展、高吞吐量、高容錯(cuò)的實(shí)時(shí)流處理;SparkR 是Spark的一個(gè)R開(kāi)發(fā)包。這些核心擴(kuò)展,除了Structured Streaming,都基于Spark 核心API處理問(wèn)題,方法幾乎是通用的,處理的數(shù)據(jù)可共享,大大提高了數(shù)據(jù)集成的靈活性。
Spark 可擴(kuò)展至大量節(jié)點(diǎn),為實(shí)現(xiàn)這個(gè)目的并最大程度的保證靈活性,Spark 支持多種資源管理器(cluster manageers),包括 Yarn、Mesos 以及 Spark 提供的Standalone,另外,local模式主要用于開(kāi)發(fā)測(cè)試。
最后,Spark 可支持多種數(shù)據(jù)集,包括本地文件系統(tǒng)、HDFS、Hbase、Cassandra等。
可見(jiàn),Spark 提供了一站式數(shù)據(jù)處理能力,這是大數(shù)據(jù)時(shí)代相對(duì)很多專用引擎來(lái)說(shuō)所不具備的。
2. Spark核心概念
2.1 基本抽象
Spark 基于兩個(gè)抽象,分別是RDDs和Shared Variables。
2.1.1 RDDs
Spark 提出了一種分布式的數(shù)據(jù)抽象,稱為 RDDs(resilient distributed datasets,彈性分布式數(shù)據(jù)集),是一個(gè)可并行處理且支持容錯(cuò)的數(shù)據(jù)集,同時(shí),也是一個(gè)受限的數(shù)據(jù)集,RDDs是一個(gè)只讀的、記錄分區(qū)的數(shù)據(jù)集,僅支持transformation和action兩種操作,這些受限,使得RDDs可以以較小的成本實(shí)現(xiàn)高容錯(cuò)性、可靠性。
RDDs有兩種創(chuàng)建方式,一種是從外部數(shù)據(jù)源創(chuàng)建,另一種是從其它RDDs transform而來(lái)。transformation 是對(duì)RDDs進(jìn)行確定性的操作,輸入是RDDs,輸出RDDs。action 是向應(yīng)用程序返回值或者將結(jié)果寫(xiě)到外部存儲(chǔ)。
最后,transformation具有 LAZY 的特點(diǎn),當(dāng)在RDDs上進(jìn)行一次transformation時(shí),并不會(huì)立即執(zhí)行,只會(huì)在進(jìn)行action時(shí),前面的transformation才會(huì)真正執(zhí)行。這個(gè)特點(diǎn),被 Spark 用來(lái)優(yōu)化整個(gè)工作鏈路,可以有效減少網(wǎng)絡(luò)溝通、傳輸時(shí)間(大數(shù)據(jù)處理過(guò)程中,網(wǎng)絡(luò)傳輸可以說(shuō)是最大的性能殺手),從而大幅提高運(yùn)行速度。
舉個(gè)例子,我們具有如下代碼:
lines = spark.textFile("hdfs://...")
errors = lines.filter(_.startsWith("ERROR"))
errors.cache()
errors.count()
第一行,讀取外部數(shù)據(jù)源,生成一個(gè)RDDs;第二行,在RDDs lines上做了一次transformation運(yùn)算 filter,取出以"ERROR" 開(kāi)頭的所有行,得到一個(gè)新的RDDs errors;第三行,緩存RDDs;第四行,在errors 上執(zhí)行action,得到errors的行數(shù)。在整個(gè)過(guò)程中,只有在執(zhí)行count()時(shí),才會(huì)真正開(kāi)始讀取數(shù)據(jù)、過(guò)濾、緩存、計(jì)算行數(shù)。

如上圖所示,展示了整個(gè)過(guò)程,稱為lineage,根據(jù)lineage,可以從具體的物理數(shù)據(jù),計(jì)算出相應(yīng)的結(jié)果。在Spark中,實(shí)現(xiàn)容錯(cuò)就是根據(jù) lineage,當(dāng)某個(gè)分區(qū)失敗后,重新進(jìn)行一次計(jì)算即可,而不是采用檢查點(diǎn)、回滾等代價(jià)高昂的方式。同時(shí),lineage 是Spark用來(lái)優(yōu)化計(jì)算流程的依據(jù)。
最后,Spark 支持RDD persist/cache。當(dāng)?shù)谝淮螆?zhí)行action時(shí),會(huì)將調(diào)用 persist() 或cache()的RDD緩存下來(lái),在下次進(jìn)行action操作時(shí),直接使用緩存數(shù)據(jù),這使得后邊的action操作速度更快,在迭代運(yùn)算或交互運(yùn)算中,緩存使用較多。
2.1.2 Shared variables
在Spark中,具體的運(yùn)算都在集群的節(jié)點(diǎn)上進(jìn)行,這些運(yùn)算操作的是從driver program 拷貝的變量的副本,且不會(huì)更新driver program上的變量,而要實(shí)現(xiàn)多任務(wù)共享的可讀寫(xiě)變量會(huì)非常低效,Spark在這方面僅支持受限的共享變量。
Broadcast variables
廣播變量是支持每臺(tái)機(jī)器持有而不是每個(gè)task持有的只讀變量,比如,給每臺(tái)機(jī)器分發(fā)大型的輸入數(shù)據(jù)集就會(huì)變得更加高效,同時(shí),Spark 采用了高效的分發(fā)算法來(lái)實(shí)現(xiàn)廣播變量的分發(fā)。
Accumulators
累加器是只被相關(guān)變量累加的變量,可以用于計(jì)數(shù)(sum)。在Spark中,原生支持?jǐn)?shù)值類型的累加器,并且可以自己實(shí)現(xiàn)對(duì)其他類型的累加器。
3. 總結(jié)
本文主要簡(jiǎn)單介紹Spark的基礎(chǔ),包括Spark的基本介紹與Spark的核心概念。在下一篇,介紹如何搭建Spark項(xiàng)目。
4. 參閱
Resilient Distributed Datasets: A Fault-Tolerant Abstraction for In-Memory Cluster Computing