重要 | Spark和MapReduce的對比,不僅僅是計算模型?


【前言:筆者將分上下篇文章進行闡述Spark和MapReduce的對比,首篇側重於"宏觀"上的對比,更多的是筆者總結的針對"相對於MapReduce我們為什么選擇Spark"之類的問題的幾個核心歸納點;次篇則從任務處理級別運用的並行機制/計算模型方面上對比,更多的是讓大家對Spark為什么比MapReduce快有一個更深、更全面的認識。通過兩篇文章的解讀,希望幫助大家對Spark和MapReduce有一個更深入的了解,並且能夠在遇到諸如"MapReduce相對於Spark的局限性?"等類似的面試題時能夠得到較好地表現,順利拿下offer】

 

>> 上篇

 

首先糾正一個誤區:在瀏覽Spark官網時,經常能看到如下這張圖:

從上圖可以看出Spark的運行速度明顯比Hadoop(其實是跟MapReduce計算引擎對比)快上百倍!相信很多人在初學Spark時,認為Spark比MapReduce快的第一直觀概念都是由此而來,甚至筆者發現網上有些資料更是直接照搬這個對比,給初學者造成一個很嚴重的誤區。

這張圖是分別使用Spark和Hadoop運行邏輯回歸機器學習算法的運行時間比較,那么能代表Spark運行任何類型的任務在相同的條件下都能得到這個對比結果嗎?很顯然是不對的,對於這個對比我們要知其然更要知其所以然。

首先,大多數機器學習算法的核心是什么?就是對同一份數據在訓練模型時,進行不斷的迭代、調參然后形成一個相對優的模型。而Spark作為一個基於內存迭代式大數據計算引擎很適合這樣的場景,之前的文章《Spark RDD詳解》也有介紹,對於相同的數據集,我們是可以在第一次訪問它之后,將數據集加載到內存,后續的訪問直接從內存中取即可。但是MapReduce由於運行時中間結果必然刷磁盤等因素,導致不適合機器學習等的迭代場景應用,還有就是HDFS本身也有緩存功能,官方的對比極有可能在運行邏輯回歸時沒有很好配置該緩存功能,否則性能差距也不至於這么大。

 

相對於MapReduce,我們為什么選擇Spark,筆者做了如下總結:

 

>> Spark 

1.集流批處理、交互式查詢、機器學習及圖計算等於一體

2.基於內存迭代式計算,適合低延遲、迭代運算類型作業

3.可以通過緩存共享rdd、DataFrame,提升效率【尤其是SparkSQL可以將數據以列式的形式存儲於內存中】

4.中間結果支持checkpoint,遇錯可快速恢復

5.支持DAG、map之間以pipeline方式運行,無需刷磁盤

6.多線程模型,每個worker節點運行一個或多個executor服務,每個task作為線程運行在executor中,task間可共享資源

7.Spark編程模型更靈活,支持多種語言如java、scala、python、R,並支持豐富的transformation和action的算子

 

>> MapReduce  

1.適合離線數據處理,不適合迭代計算、交互式處理、流式處理

2.中間結果需要落地,需要大量的磁盤IO和網絡IO影響性能

3.雖然MapReduce中間結果可以存儲於HDFS,利用HDFS緩存功能,但相對Spark緩存功能較低效

4.多進程模型,任務調度(頻繁申請、釋放資源)和啟動開銷大,不適合低延遲類型作業

5.MR編程不夠靈活,僅支持map和reduce兩種操作。當一個計算邏輯復雜的時候,需要寫多個MR任務運行【並且這些MR任務生成的結果在下一個MR任務使用時需要將數據持久化到磁盤才行,這就不可避免的進行遭遇大量磁盤IO影響效率】


但是,雖然Spark相對於MapReduce有很多優勢,但並不代表Spark目前可以完全取代MapReduce。

筆者之前負責的一個任務,數據存儲格式是parquet,壓縮比比較高,解壓后數據量劇增,又加上存在一些大字段問題,任務比較復雜僅sql語句就幾千行,導致Spark處理時總是報OOM,在有限的資源試了各種調優方法都不能使任務正常穩定的運行。最后改用Hive的原生引擎MapReduce執行,在資源配置相同的情況下,任務能夠穩定運行,而且速度並沒有想象中的那么慢。所以,對於技術之間的對比以及應用,還是建議首先要對技術本身有深入的理解比如設計思想、編程模型、源碼分析等,並且要結合實際的業務場景需求等,不能空談技術。


>> 下篇

 

【前言:本文主要從任務處理的運行模式為角度,分析Spark計算模型,希望幫助大家對Spark有一個更深入的了解。同時拿MapReduce和Spark計算模型做對比,強化對Spark和MapReduce理解】

從整體上看,無論是Spark還是MapReduce都是多進程模型。如,MapReduce是由很多MapTask、ReduceTask等進程級別的實例組成的;Spark是由多個worker、executor等進程級別實例組成。但是當細分到具體的處理任務,MapReduce仍然是多進程級別,這一點在文章《詳解MapReduce》已有說明。而Spark處理任務的單位task是運行在executor中的線程,是多線程級別的。

對於多進程,我們可以很容易控制它們能夠使用的資源,並且一個進程的失敗一般不會影響其他進程的正常運行,但是進程的啟動和銷毀會占用很多時間,同時該進程申請的資源在進程銷毀時也會釋放,這就造成了對資源的頻繁申請和釋放也是很影響性能的,這也是MapReduce廣為詬病的原因之一。
對於MapReduce處理任務模型,有如下特點:

1.每個MapTask、ReduceTask都各自運行在一個獨立的JVM進程中,因此便於細粒度控制每個task占用的資源(資源可控性好)

2.每個MapTask/ReduceTask都要經歷申請資源 -> 運行task -> 釋放資源的過程。強調一點:每個MapTask/ReduceTask運行完畢所占用的資源必須釋放,並且這些釋放的資源不能夠為該任務中其他task所使用

3.可以通過JVM重用在一定程度上緩解MapReduce讓每個task動態申請資源且運行完后馬上釋放資源帶來的性能開銷

但是JVM重用並不是多個task可以並行運行在一個JVM進程中,而是對於同一個job,一個JVM上最多可以順序執行的task數目,這個需要配置參數mapred.job.reuse.jvm.num.tasks,默認1。

對於多線程模型的Spark正好與MapReduce相反,這也決定了Spark比較適合運行低延遲的任務。在Spark中處於同一節點上的task以多線程的方式運行在一個executor進程中,構建了一個可重用的資源池,有如下特點:

1.每個executor單獨運行在一個JVM進程中,每個task則是運行在executor中的一個線程。很顯然線程線程級別的task啟動速度更快

2.同一節點上所有task運行在一個executor中,有利於共享內存。比如通過Spark的廣播變量,將某個文件廣播到executor端,那么在這個executor中的task不用每個都拷貝一份處理,而只需處理這個executor持有的共有文件即可

3.executor所占資源不會在一些task運行結束后立即釋放掉,可連續被多批任務使用,這避免了每個任務重復申請資源帶來的開銷

但是多線程模型有一個缺陷:同一節點的一個executor中多個task很容易出現資源征用。畢竟資源分配最細粒度是按照executor級別的,無法對運行在executor中的task做細粒度控制。這也導致在運行一些超大數據量的任務並且資源比較有限時,運行不太穩定。相比較而言,MapReduce更有利於這種大任務的平穩運行。

 


 

關注微信公眾號:大數據學習與分享,獲取更對技術干貨


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM