Apache Spark 2.0簡介,那些你想知道的事都在這里了
今天介紹一篇文章,詳細(xì)闡述了Apache Spark 2.0突出的三大優(yōu)點(diǎn):更容易、更快速、更智能。
兩個月前,我們在Databricks上發(fā)布了Apache Spark 2.0的預(yù)覽版本。從下面的圖表可以看出,我們的10%的集群已經(jīng)使用這個版本,同時客戶試用了其新功能,并向我們提供了反饋意見。
隨時間的推移各個不同版本Apache Spark的使用情況
現(xiàn)在,讓我們一起更深入地了解Apache Spark 2.0的新功能。
更容易:ANSI SQL和簡化版的API
我們?yōu)镾park感到特別自豪的一件事是簡單、直觀和表達(dá)性強(qiáng)的API。Spark 2.0繼續(xù)了這一傳統(tǒng),其重點(diǎn)關(guān)注以下兩大領(lǐng)域:
- 標(biāo)準(zhǔn)SQL支持
- 統(tǒng)一DataFrame/Dataset API。
在SQL方面,我們已經(jīng)大大擴(kuò)展了Spark的SQL支持功能,并引入了一個新的ANSI SQL解析器和對子查詢(subqueries)的支持?,F(xiàn)在,Spark 2.0已經(jīng)可以運(yùn)行TPC-DS的所有99個查詢,這99個查詢需要諸多的SQL:2003特性。因為SQL一直是Spark的主要接口之一,因此這些擴(kuò)展功能大大降低了移植舊應(yīng)用程序的工作量。
在程序化API方面,我們已經(jīng)簡化了Spark的API:
統(tǒng)一Scala和Java中DataFrames和Datasets:從Spark 2.0開始,DataFrame只是Dataset of Row的類型別名。Dataset類同時支持類型化方法(例如map、filter,groupByKey)和非類型化方法(例如select、groupBy)。此外,這個新的組合型Dataset接口是用于結(jié)構(gòu)化流(Structured Streaming)的抽象。
由于編譯時類型安全性在Python和R中并不是語言特性,因此Dataset的概念不適用于這些語言API。相反,DataFrame仍然是它們的主接口,并且類似于這些語言中的單節(jié)點(diǎn)數(shù)據(jù)幀概念。
SparkSession: 這是一個新的切入點(diǎn),取代了舊的SQLContext和HiveContext。對于DataFrame API的用戶而言,Spark的一個常見的容易產(chǎn)生困惑的地方就是我們正在使用哪個“運(yùn)行環(huán)境”?,F(xiàn)在您可以使用SparkSession作為單一切入點(diǎn),其同時涵括了SQLContext和HiveContext的功能。請注意,舊版本的SQLContext和HiveContext類仍然保持向后兼容性。
更容易、更高性能的累加器API(Accumulator API):我們設(shè)計了一個新的累加器API(Accumulator API),它具有更加簡潔的類型層次結(jié)構(gòu),并支持原語類型的專門化。舊版本的Accumulator API已經(jīng)棄用,但仍然保留了向后兼容性。
- 基于DataFrame的機(jī)器學(xué)習(xí)API成為主要的ML API:在Spark 2.0中,spark.ml包及其“管道”API將成為主要的機(jī)器學(xué)習(xí)API。雖然原始spark.mllib包被保留,但未來的開發(fā)將集中在基于DataFrame的API上。
- 機(jī)器學(xué)習(xí)管道持久化:用戶現(xiàn)在可以利用Spark支持的所有編程語言保存和加載機(jī)器學(xué)習(xí)管道和模型。
- 以R語言編寫的分布式算法:增加對以R語言編寫的廣義線性模型(Generalized Linear Models,GLM)、樸素貝葉斯(Naive Bayes)、生存回歸(Survival Regression)和K均值(K-Means)的支持。
以R語言編寫的用戶定義函數(shù)(UDF):增加對運(yùn)行分區(qū)級別UDF(dapply和gapply)和超參數(shù)調(diào)整(lapply)的支持。
更快速:Apache Spark作為編譯器
根據(jù)我們2015年Spark調(diào)查報告顯示,91%的用戶認(rèn)為性能是Apache Spark最為重要的考慮因素。因此,性能優(yōu)化始終是我們Spark開發(fā)的重點(diǎn)。在我們開始規(guī)劃對Spark 2.0的性能改進(jìn)之前,我們問了自己一個問題:雖然Spark已經(jīng)相當(dāng)快了,但是我們是否可以將其推向性能極限,使Spark 的運(yùn)行速度再提升十倍呢?
帶著這個問題我們從根本上重新思考了Spark物理執(zhí)行層的設(shè)計方式。當(dāng)您隨便調(diào)查一個現(xiàn)代數(shù)據(jù)引擎(例如,Spark或其他MPP數(shù)據(jù)庫)時,您會發(fā)現(xiàn)大多數(shù)CPU周期都消耗在無用的工作上,比如進(jìn)行虛擬函數(shù)調(diào)用或讀取/寫入中間數(shù)據(jù)到CPU高速緩存或內(nèi)存中。通過減少在這些無用工作中浪費(fèi)的CPU周期數(shù)量來優(yōu)化性能已經(jīng)是現(xiàn)代編譯器的一直以來關(guān)注的熱點(diǎn)。
Spark 2.0中配備了第二代Tungsten引擎。這一代引擎是建立在現(xiàn)代編譯器和MPP數(shù)據(jù)庫的想法上,并且把它們應(yīng)用于數(shù)據(jù)的處理過程中。其主要想法是通過在運(yùn)行期間優(yōu)化那些拖慢整個查詢的代碼到一個單獨(dú)的函數(shù)中,消除虛擬函數(shù)的調(diào)用以及利用CPU寄存器來存放那些中間數(shù)據(jù)。我們把這些技術(shù)統(tǒng)稱為“整段代碼生成”(whole-stage code generation)。
為了有個直觀的感受,我們記錄下在Spark 1.6和Spark 2.0中在一個核上處理一行的操作時間(單位是納秒)。下面的表格能夠體現(xiàn)出Spark 2.0中新的Tungsten引擎的威力。Spark 1.6使用的表達(dá)式代碼生成技術(shù)同樣在今天的一些最先進(jìn)的商業(yè)數(shù)據(jù)庫中采用,但是您可以看到,許多運(yùn)算符在采用了“整段代碼生成”(whole-stage code generation)技術(shù)之后速度提升了一個數(shù)量級。
在本筆記本中,您可以看到“整段代碼生成”(whole-stage code generation)技術(shù)的威力,在這里我們在一臺機(jī)器上對10億條記錄進(jìn)行Aggregation和Join操作。
那么在新的Tungsten引擎在端至端的查詢表現(xiàn)又會怎樣?我們比較了Spark 1.6和Spark 2.0在使用TPC-DS查詢的基本分析,如下圖所示:
除了“整段代碼生成”(whole-stage code generation)可以提高性能之外,Catalyst優(yōu)化器方面也做了許多的工作,比如改進(jìn)通用查詢優(yōu)化(例如,為空性傳播(nullability propagation));還有一個新的矢量化Parquet解碼器,它使得Parquet的掃描吞吐量提高了3倍。
更智能:結(jié)構(gòu)化流(Structured Streaming)
Spark Streaming在大數(shù)據(jù)領(lǐng)域第一次嘗試將批處理和流計算進(jìn)行了統(tǒng)一。在Spark 0.7版本開始引入的第一個流式API稱為DStreams,它為開發(fā)者提供了幾項強(qiáng)大的特性:恰好一次的語義、大規(guī)模容錯、強(qiáng)一致性保證和高吞吐量。
然而,隨著數(shù)百個真實的Spark Streaming部署之后,我們發(fā)現(xiàn),需要實時作出決策的應(yīng)用程序通常需要不止一個流引擎。他們需要深度地將批處理堆棧和流處理堆棧進(jìn)行整合;需要和外部存儲系統(tǒng)進(jìn)行交互;以及需要應(yīng)付業(yè)務(wù)邏輯變化的能力。其結(jié)果是,企業(yè)需要的不僅僅是一個流式引擎;相反,他們需要一個完整的堆棧,使他們能夠開發(fā)終端到終端的“持續(xù)應(yīng)用程序”。
Spark 2.0通過一種稱為結(jié)構(gòu)化流(Structured Streaming)的新API來處理這些使用案例。與現(xiàn)有的流系統(tǒng)相比,結(jié)構(gòu)化流(Structured Streaming)主要做了以下三個方面的改進(jìn):
1、集成API與批處理作業(yè)。如需運(yùn)行流計算,開發(fā)人員只需對DataFrame/Dataset API編寫一個批處理計算,然后Spark會自動遞增計算以便以流方式運(yùn)行(即在數(shù)據(jù)進(jìn)入時更新結(jié)果)。這種強(qiáng)大的設(shè)計意味著開發(fā)人員不必手動管理狀態(tài)、故障或保持應(yīng)用程序與批處理作業(yè)同步。相反,流式作業(yè)總能給出與同一數(shù)據(jù)上的批處理作業(yè)相同的答案。
2、與存儲系統(tǒng)之間的事務(wù)交互。結(jié)構(gòu)化流(Structured Streaming)能夠在整個引擎和存儲系統(tǒng)中保持容錯性和一致性,從而可以很容易地編寫應(yīng)用程序,該應(yīng)用程序能夠更新用于服務(wù)的實時數(shù)據(jù)庫,加入靜態(tài)數(shù)據(jù)或在存儲系統(tǒng)之間可靠地移動數(shù)據(jù)。
3、與Spark其余部分的豐富集成。結(jié)構(gòu)化流(Structured Streaming)支持通過Spark SQL對流數(shù)據(jù)進(jìn)行交互式查詢,對靜態(tài)數(shù)據(jù)進(jìn)行連接,以及許多已經(jīng)使用DataFrames的庫,同時讓開發(fā)人員構(gòu)建完整的應(yīng)用程序,而不僅僅是流管道。未來,期望與MLlib和其他庫實現(xiàn)更多的集成。
作為實現(xiàn)這一愿景的第一步,Spark 2.0附帶了一個初始的alpha版本的結(jié)構(gòu)化流(Structured Streaming),其擴(kuò)展自DataFrame/Dataset API(令人驚訝的小!)。這個統(tǒng)一對現(xiàn)有的Spark用戶比較容易適應(yīng),因為這讓他們能夠充分利用Spark批量處理API知識來解決實時中的新問題。其它主要功能將包括支持基于事件時間的處理、亂序/延時數(shù)據(jù)、交互式查詢以及非流數(shù)據(jù)源和接收器的緊密集成。
此外,我們還更新了Databricks工作空間以支持結(jié)構(gòu)化流(Structured Streaming)。例如,當(dāng)啟動流查詢時,筆記本UI將自動顯示其狀態(tài)。
Streaming顯然是一個非常寬泛的話題,所以敬請多關(guān)注,以了解Apache Spark 2.0中的結(jié)構(gòu)化流(Structured Streaming)的更多詳細(xì)信息。



























