Spark基本概念簡介

1 Hadoop等大數據分析工具的問題以及未來趨勢
有問題纔有發展,如果Hadoop足夠完美,那麼就沒有Spark什麼事了。但是有兩個因素決定不可能有完美的東西:一、只要稍微複雜點的東西就無法保證像1+1=2那樣完美無瑕;二、任何事物無法逃脫時代的侷限性,也就是時代發展了,這些東西就過期了。
那麼現在的hadoop有什麼問題呢?
  • 最大的也是吐槽最多的一個問題自然是hadoop的MR只是一個框架,就像J2EE一樣。如果你要使用,你必須有一個碼農將你的業務邏輯實現成Java(或者其他語言)代碼。每當有業務升級,代碼也得相應升級。易用性受到極大的限制,這也是Hive、Pig等產品的出發點。
  • 另外MR的框架並不是完美的,有一些邏輯使用MapReduce無法非常好的實現,因爲每個Map或者每個Reducer之間都是無關聯的。只有一個partition能夠做一次數據的重組。舉個最簡單的例子:我們要按照一個公共key拼接兩個數據,數據1中每條數據的key爲A1,A2,A3,而數據B中的每條數據的key爲Ai。那麼我們無法實現分桶,因爲數據1無法確定要去哪個reduce,我們只能將數據1拷貝多份,扔到好幾個reducer中去。
  • 還有一個是Hadoop大量使用了磁盤,磁盤的IO實在不敢恭維。比如我們的計算是一個串行的流,我們每個MR的中間結果還得扔到磁盤中去,其實這些中間結果並不需要持久化。
  • 還有包括namenode的單點問題等問題
而Spark就是爲了解決這些問題而生的。
2 Spark的特色
我們打開Spark的主頁可以看到Spark的幾個特點:
  • Speed:內存計算速度是hadoop的100倍,磁盤計算則是10倍(Spark擁有更高級的DAG框架以及內存計算功能)
  • Ease of Use:可以使用Scala、Java或者python快速開發(擁有超過80個的抽象操作集成在Spark API中)
  • Generality:集合了Streaming、SQL以及高級數據處理等功能(其實就是在Spark之上可以使用Shark SQL、Shark Streaming、MLLib(machine learning lib)、GraphX等軟件而已)
  • Integrated with Hadoop:完美支持Hadoop(可以在Yarn上面跑Spark,可以使用HDFS數據進行Spark計算,其實這就是爲了吸引Hadoop的用戶)
我們簡單看一下可以看到,其中2、3都是爲了提高易用性,方便實現更多的業務,同時支持更快的開發。而1爲了提高執行效率。至於4我們暫時不需要理會,這是一個產品推廣的特色。我們看到Spark在推廣的時候刺中了Hadoop的許多痛點,讓那些在使用Hadoop的人頓時感覺到:我靠,原來還有這麼好使的東西,那我還玩什麼Hadoop,趕緊從了Spark吧!說句題外話,這也是做宣傳的一個好方法,宣揚同類產品的不足之處,拿自己的優點和別人的缺點比。你可以看到老羅做手機發佈會的時候必然會這麼搞。
3 Spark的關鍵特性RDD
這一節描述下Spark的關鍵特性:RDDs(Resilient Distributed Datasets)。RDD具有許多重要的特性,可以簡單劃分成:內存計算、故障容忍兩部分。
3.1 RDD簡介
RDDs是Spark的核心內容,大家可以通過研讀這篇論文來學習RDD的相關內容(PS:這篇論文有點老,也許現在的Spark又進步了)。RDD在Spark的官方文檔中的解釋爲:RDD is a fault-tolerant collection of elements that can be operated on in parallel。我們關注幾個關鍵詞:fault-tolerant、in parallel。首先它是故障容忍的,其實它是並行計算的element(可以理解爲數據)。事實上RDD提出了兩個重要的思想:1.將數據cache在內存中,大大減少磁盤的IO;2.方便而快速的恢復某些RDD失效的問題。當然,在易用性方面,RDD也是非常高端,提供了大量的API,但是本文就不討論了,因爲技術上面意義不大。
3.2 RDD的作用和意義
通過上面貼的那篇論文,我們可以知道RDD可以解決兩類常見的應用問題,一類叫做iterative(迭代)計算,比如machine learning、graph algorithm(機器學習和圖形算法),另一類叫做interactive(交互)計算,比如對一份大數據進行大量的ad-hoc查詢。第一類計算遇到的問題是中間結果會被重複使用,如果使用MR框架,這些中間結果需要持久化到磁盤,每次使用得再讀磁盤,太慢了!第二類計算遇到的問題是,這一份大數據放在磁盤中,我每次查詢都得讀磁盤,太慢了!所以內存計算應運而生。RDD將這些需要重複使用的數據放置到內存中,使得數據的計算速度大大加快,這也就是前面提到的比hadoop快XXX倍的一大原因。而我們可以看到,這個RDD的根本出發點就在於,有些數據我們往往會多次使用,放到內存必然能夠加快訪問速度。
某些同學可能都已經看出來了,其實這就是cache的原理——將某些數據cache到高一級的存儲介質中,以命中cache來減少對低級存儲的訪問頻率
3.3 內存計算
看了上面的解釋,其實大家已經比較清楚內存計算這件事情了——不過就是把數據放到內存中而已。
更詳細的,Spark中將計算分爲兩類:Action和Transformation。Action是指不產生新數據集的計算,比如count(統計行數)、比如reduce(彙集數據,是的,它不產出新的數據,只是彙集而已)。而相應的Transformation則是產生新數據集的計算,比如map、filter、union(拼接)。顯然可以看到Transformation纔是我們要關注的內容,因爲涉及到中間數據的問題。那麼Transformation可以認爲是從一個或多個RDD到另一個或者多個RDD的操作。那麼這些操作可以用一個DAG圖來完全描述,所有的節點都是一個RDD,而有向邊則是transformation。這樣我們就可以將其中那些出度(Out-degree)較大的節點存到內存中,這樣,這些使用此節點的transformation都可以得到更高的執行速度。回到前面說的interactive計算,就是這個情況的最好樣例,大量的ad-hoc查詢都會訪問基礎數據,所以將其放置在內存中是個great idea!
需要注意的是,Spark爲我們提供了最大的自由度,所有的數據都可以由我們來進行cache的設置,包括是否要cache以及如何cache。cache有幾種:
  • MEMORY_ONLY:內存、非序列化方式,最快,但是如果超過內存限制,則會將某些數據丟棄,在需要的時候再計算(recomputed on the fly)
  • MEMORY_AND_DISK:基本同上,唯一不同是,如果超過內存限制,存到磁盤
  • MEMORY_ONLY_SER:和MEMORY_ONLY一致,但是會序列化
  • MEMORY_AND_DISK_SER:和MEMORY_AND_DISK類似,但是會序列化
  • DISK_ONLY:磁盤
最後cache還可以做副本,防止數據丟失重算。我們可以看到這個cache的方案相當完善,自由度相當大。
最後還有一個問題是內存中的數據expire,如果有大量的數據要進入內存,那麼Spark會採用LRU(least recent used)算法清除某些RDD,據論文介紹,LRU還是非常好使的。
3.4 故障容忍
故障容忍是指如果數據的某個partition(塊)缺失了,那麼可以通過重新計算的方式,將這一塊partition再次生成。這裏RDD首先要解決一個依賴的問題
3.4.1 NARROW DEPENDENCY和WIDE DEPENDENCY
依賴分爲兩種:narrow dependency和wide dependency。前者是指——單純的一對一依賴,也就是我們熟知的map操作,我們通過一塊數據產出了另一塊數據,比如簡單的filter就是。後者是指——複雜的多對多依賴,聰明的同學可能已經知道了,就是類似reduce的依賴,比如group by key。Spark必須支持這兩種依賴,因爲他們都無可替代。

通過依賴的劃分,我們可以將計算流變成更爲簡單的DAG圖,而不是按照RDD來進行區分。論文中提出了stage這個概念:連續的narrow依賴可以合併成一個stage,因爲他們可以在一個數據存放node本地執行。

3.4.2 故障恢復

當某個塊丟失,Spark就會嘗試恢復這一個塊,那麼會根據整個DAG圖中的數據流來查閱數據,如果某個數據已經在內存中,就不需要再計算了,否則需要執行一次計算。最終將數據計算出來。那麼我們來看兩種dependency對恢復的影響。我們可以看到narrow依賴可以更方便的恢復,因爲一塊數據對應另一塊數據。我們爲了恢復某一個數據,只需要使用它對應的另一塊源數據計算就可以了。但是wide依賴就麻煩多了,某一塊數據的數據源來自衆多的塊,我們只能將上游全部計算才能恢復數據。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章