作爲Hadoop的分佈式計算框架,MapReduce扮演着分佈式計算的任務,適用於離線批計算任務。Spark本身不具備存儲數據功能,通常基於HDFS。我們經常會在各類文章中看到類似這樣的描述:Spark是基於內存計算的,其速度遠快於Hadoop的MapReduce。本文旨在討論這一結論背後的原因。
一、Spark內存計算 VS MapReduce讀寫磁盤
-
MapReduce:MapReduce通常需要將計算的中間結果寫入磁盤。map進程和reduce進程需要讀取指定位置的數據作爲輸入,如果不將中間結果寫入磁盤以保證可靠存儲,一旦中間結果丟失或者損壞,MapReduce沒有機制能夠恢復中間結果。此外,一個job可能涉及到多個stage,而每個stage的處理結果都需要存儲到HDFS中,這就必然導致頻繁的磁盤IO;
-
Spark:Spark不需要將計算的中間結果寫入磁盤,這得益於Spark的RDD(彈性分佈式數據集)和DAG(有向無環圖),前者是Spark中引入的一種只讀的、可擴展的數據結構,後者則記錄了job的stage以及在job執行過程中父RDD和子RDD之間的依賴關係。中間結果能夠以RDD的形式存放在內存中,一旦Job中的某個RDD丟失或者損壞,則可以根據DAG來重新計算得到該RDD。此外,在Spark中一個job的多個stage任務可以串聯或者並聯執行,stage的中間結果不需寫入HDFS。
我們知道頻繁的磁盤IO非常影響系統的處理性能,而基於內存計算則大大提升了處理性能。
二、其他區別
2.1 任務調度
-
Hadoop的MapReduce是針對大文件的批處理而設計的,延遲較高;
-
Hadoop的MapReduce的Map Task和Reduce Task都是進程級別的,而Spark Task則是基於線程模型的(而mapreduce 中的 map 和 reduce 都是 jvm 進程,每次啓動都需要重新申請資源,啓動時間大概1s;想象一下如果是8096個block,那麼單獨啓動map進程事件就需要8096秒,非常影響效率;);
-
Spark通過複用線程池中的線程來減少啓動、關閉task所需要的開銷。
2.2 執行策略
-
MapReduce在shuffle前需要花費大量時間進行排序;
-
Spark在shuffle時只有部分場景才需要排序,支持基於Hash的分佈式聚合,更加省時;
2.3 數據格式和內存佈局
-
MapReduce Schema on Read處理方式會引起較大的處理開銷;
-
Spark RDD能支持粗粒度寫操作,對於讀操作則可以精確到每條record,因此RDD可以用來作爲分佈式索引。此外用戶可以自定義分區策略,如Hash分區等。Shark和Spark SQL在Spark的基礎上實現了列存儲和列存儲壓縮。
往期推薦
2、MapReduce Shuffle 和 Spark Shuffle 結業篇