王軍
(西安外事學院,陜西西安,710077)
工業(yè)和研究領域數(shù)據(jù)量的增長帶來了巨大的機遇,同時也帶來了巨大的計算挑戰(zhàn)。由于數(shù)據(jù)規(guī)模已經(jīng)超出了單機的計算能力,用戶需要新系統(tǒng)將計算擴展到多個計算節(jié)點。因此,針對不同計算負載的新型集群編程模型大量涌現(xiàn)。剛開始,這些模型相對專業(yè)化,為解決新的負載問題開發(fā)新模型。例如,MapReduce支持批處理,但Google也開發(fā)了用于交互式SQL查詢的Dremel和用于迭代圖算法的Pregel。在開源的Apache Hadoop堆棧中,Storm和Impala等系統(tǒng)也是為專門的運算開發(fā)的。即使在關系數(shù)據(jù)庫領域里,基本趨勢也是要避免“通用”的系統(tǒng)。然而現(xiàn)實情況中大多數(shù)大數(shù)據(jù)應用程序需要結合許多不同的處理類型。“大數(shù)據(jù)”的本質(zhì)在于它是多樣性和無序性;典型的工作流程需要類似MapReduce的代碼用于數(shù)據(jù)加載、類似SQL的查詢以及迭代機器學習,使用專門的引擎會造成系統(tǒng)更加復雜,效率低下。為此,用戶還必須將不同的系統(tǒng)連接在一起,某些應用程序甚至根本無法在任何引擎中高效表達。
Spark框架編程的核心概念是彈性分布式數(shù)據(jù)集(RDDs),RDD是跨群集分區(qū)對象的容錯集合。Spark通過Scala、Java、Python和R等編程語言中的功能性API來提供RDD接口,用戶通過對自己的數(shù)據(jù)申請轉(zhuǎn)換操作(如map、filter和groupBy等)來創(chuàng)建RDD。Spark允許RDD為用戶的計算找到一個有效的計劃,用戶的轉(zhuǎn)換操作返回一個表示計算結果的新RDD對象,當一個動作被調(diào)用時,Spark會查看用于創(chuàng)建執(zhí)行計劃的整個轉(zhuǎn)換圖,進而進行計算。
除了提供數(shù)據(jù)共享和各種并行操作外,RDD還可以自動從故障中恢復,因而具有很強的容錯能力。傳統(tǒng)的分布式計算系統(tǒng)通過數(shù)據(jù)復制或檢查點提供容錯功能,而Spark采用一種稱為“l(fā)ineage”的方法,每個RDD跟蹤用于構建它的轉(zhuǎn)換圖,并在基礎數(shù)據(jù)上重新執(zhí)行轉(zhuǎn)換操作以重建任何丟失的分區(qū)。基于lineage的恢復比數(shù)據(jù)密集型工作負載中的復制效率更高,因為通過網(wǎng)絡寫入數(shù)據(jù)比將數(shù)據(jù)寫入RAM以及存儲器的存儲空間要慢得多。有損節(jié)點通常包含多個RDD分區(qū),這些分區(qū)可以在其他節(jié)點上并行重建,因而恢復通常比重新運行程序快得多。
Spark與存儲系統(tǒng)具有良好的集成性能。與谷歌的MapReduce很像,Spark被設計為與多個外部系統(tǒng)一起用于長期存儲。Spark最常用于集群文件系統(tǒng),如HDFS、S3和Cassandra等的鍵值存儲,它也可以連接Apache Hive作為數(shù)據(jù)目錄。雖然Spark SQL JDBC服務器等應用程序也可以在多個用戶之間共享RDD,而RDD通常僅在應用程序中存儲臨時數(shù)據(jù)。Spark引擎與存儲系統(tǒng)無關的設計理念使用戶可以輕松地針對現(xiàn)有數(shù)據(jù)運行計算并增加多種數(shù)據(jù)源。
RDD編程模型僅提供對象和函數(shù)的分布式集合, Spark使用RDD針對許多專用計算引擎構建了各種更高級的庫。核心的思想是,控制存儲在RDD中的數(shù)據(jù)結構、跨節(jié)點的數(shù)據(jù)分區(qū)以及在其上運行的功能,就可以在其他引擎中實現(xiàn)許多執(zhí)行操作。事實上,這些庫通??梢葬槍θ蝿仗峁┳顑?yōu)秀的性能,同時在庫組合使用時也具有顯著的優(yōu)勢。現(xiàn)討論Apache Spark包含的四個主要庫。
SQL和DataFrames。數(shù)據(jù)處理中最常見的應用之一是關系查詢,Spark SQL及其前身Shark 23使用類似于分析數(shù)據(jù)庫的技術在Spark上執(zhí)行關系查詢。這些系統(tǒng)支持列式存儲、基于成本的優(yōu)化和用于查詢執(zhí)行情況的代碼生成,背后的主要思想是使用與分析數(shù)據(jù)庫相同的數(shù)據(jù)布局,即壓縮列式存儲和內(nèi)部RDD。在Spark SQL中,RDD中的每條記錄都包含一系列以二進制格式存儲的行數(shù)組,系統(tǒng)會生成代碼以直接針對這些行數(shù)組來運行。
除了運行SQL查詢之外,Spark SQL引擎為基本數(shù)據(jù)轉(zhuǎn)換DataFrames提供了更高級別的抽象,這些數(shù)據(jù)轉(zhuǎn)換是具有確定模式的RDD。DataFrames是R和Python中表格數(shù)據(jù)的常用抽象方式,用于過濾、計算和聚合新列的編程方法。在Spark中,這些操作映射到Spark SQL引擎并接收其所有優(yōu)化。
Spark Streaming。Spark Streaming使用“離散化流”模型實現(xiàn)增量流處理。為了實現(xiàn)Spark的流式處理,我們將輸入數(shù)據(jù)在時間上(如每200毫秒)進行分割,再與RDD中存儲的狀態(tài)相結合來產(chǎn)生新結果。由于使用譜系故障恢復較為便宜,因此可以將流式傳輸與批處理和交互式查詢結合起來。
GraphX。GraphX提供了一個類似于Pregel和GraphLab的圖形計算界面,通過為其構建的RDD選擇分區(qū)功能,實現(xiàn)與這些系統(tǒng)相同的布局優(yōu)化。
MLlib。MLlib是Spark的機器學習庫,實現(xiàn)了50多種分布式模型訓練的常用算法,包括決策樹(PLANET)、潛在狄利克雷分配和交替最小二乘矩陣分解等。
Spark庫可以在數(shù)據(jù)的所有RDD上運行,因而它們在應用程序中的組合也相對容易。由于Spark提供跨處理庫的優(yōu)化功能,因此除了在API層的兼容性,Spark的庫組合在執(zhí)行層也很有效。如果一個庫運行映射函數(shù),另外一個庫在其映射結果上運行另外一個映射,則Spark將這些操作融合到一個映射中。同樣,Spark的故障恢復功能可以在這些庫中無縫連接,無論哪個庫生成它,都可以重新計算丟失的數(shù)據(jù)。
本文介紹了Apache Spark的發(fā)展歷史,并詳細介紹了編程模型并且解釋了其非常普遍的原因,針對高層庫介紹了ApacheSpark四個常用的庫,以及這些庫之間的相互調(diào)用的組合使用方法和應當注意的問題。對研究基于ApacheSpark的分布式大數(shù)據(jù)處理具有很好的參考價值。