首先大資料涉及兩個方面:分散式儲存系統和分散式計算框架。前者的理論基礎是GFS。後者的理論基礎為MapReduce。MapReduce框架有兩個步驟(MapReduce 框架其實包含5 個步驟:Map、Sort、Combine、Shuffle 以及Reduce。這5 個步驟中最重要的就是Map 和Reduce。這也是和Spark 最相關的兩步,因此這裡只討論這兩個步驟):一個是 Map,另一個是 Reduce。Map 步驟是在不同機器上獨立且同步執行的,它的主要目的是將資料轉換為 key-value 的形式;而 Reduce 步驟是做聚合運算,它也是在不同機器上獨立且同步執行的。Map 和 Reduce 中間夾雜著一步資料移動,也就是 shuffle,這步操作會涉及數量巨大的網路傳輸(network I/O),需要耗費大量的時間。 由於 MapReduce 的框架限制,一個 MapReduce 任務只能包含一次 Map 和一次 Reduce,計算完成之後,MapReduce 會將運算結果寫回到磁碟中(更準確地說是分散式儲存系統)供下次計算使用。如果所做的運算涉及大量迴圈,比如估計模型引數的梯度下降或隨機梯度下降演算法就需要多次迴圈使用訓練資料,那麼整個計算過程會不斷重複地往磁盤裡讀寫中間結果。這樣的讀寫資料會引起大量的網路傳輸以及磁碟讀寫,極其耗時,而且它們都是沒什麼實際價值的廢操作。因為上一次迴圈的結果會立馬被下一次使用,完全沒必要將其寫入磁碟。整個演算法的瓶頸是不必要的資料讀寫,而Spark 主要改進的就是這一點。具體地,Spark 延續了MapReduce 的設計思路:對資料的計算也分為Map 和Reduce 兩類。但不同的是,一個Spark 任務並不止包含一個Map 和一個Reduce,而是由一系列的Map、Reduce構成。這樣,計算的中間結果可以高效地轉給下一個計算步驟,提高演算法效能。雖然Spark 的改進看似很小,但實驗結果顯示,它的演算法效能相比MapReduce 提高了10~100 倍。另:在MapReduce 框架下,資料的格式都是key-value 形式,其中key 有兩個作用:一方面它被用作統計的維度,類似於SQL 語句裡面的group by 欄位,比如正文例子裡的字元;另一方面它又被用作資料的“指南針”決定資料將被髮送到哪臺機器上。而後者是分散式計算框架的核心。在某些計算場景下,計算本身不需要key 值,或者說不需要Map 這一步,比如對一個數字陣列求和。這種情況下,系統會自動地生成一個Map 用於將資料轉換為key-value 形式,這時key 值就只被用作資料的“指南針”。