谷歌 MapReduce 比 Spark 強在哪裏?

10 幾年前,大家聊大數據總是聊這樣的一個故事。谷歌的三駕馬車開啓了大數據的新時代。然後 Hadoop 則帶來了開源的生態。當然,和谷歌同一個時代的還有 Michael Stonebraker 說的 MapReduce-a major step backward。

之後就是和 Hadoop 生態圈若即若離的 Spark,一開始通過猥瑣發育,和 Hadoop 打成一片,後來自己開始做 Spark Summit,幹翻了整個 Hadoop,成爲了現在大數據領域當之無愧的標準。

這麼多年過去了,谷歌的 MapReduce 也發展出了 Flume,在內部使用。當然同一個團隊還做了 Millwheel 的流引擎。但是有一個問題可能一直都沒被人討論過:谷歌的 MapReduce 到底比 Spark 強在哪裏?

這個問題可以換個說法,谷歌的 MapReduce 和 Hadoop 的 MapReduce 有什麼不一樣嗎?

其實問題都是等價的。我們先看看 Spark 吧。Spark 從誕生到今天,有一個問題一直都在困擾着 Spark,這個問題就是 shuffle。

Spark 做 shuffle 的辦法是(我簡化一下),每個 Mapper 把自己的 shuffle 文件寫到本地盤,然後,後面的 executor 就可以來讀這些文件了。

這個做法有一個要求,這個寫了本地文件的 executor 必須活着,不然的話這些本地文件也跟着丟了。丟了只能從上一步開始重新執行。所以一旦因爲什麼原因導致這個 executor 被砍,就會付出巨大代價。

解決問題的辦法,好像是 Spark 1.2 就開始有了,可以引入一個 external shuffle service。讓這個 long running process 來接管這些文件的控制。這個做法不是沒有副作用,這很容易就導致本地盤被寫滿。

由於這個寫本地盤讀本地盤的問題,Uber,LinkedIn 等公司又開始引入自己的 external shuffle service。而 Spark3 開始引入的 dynamic allocation 又導致了一些其他問題,這使得 Spark 開始記錄哪些本地 shuffle 文件被哪些 executor 給使用了,以及爲了防止一個 executor 跑太久,還增加了最久多久要 timeout 的選項等等。這個問題還導致了 K8S 做 autoscaling 的時候 scale down 總出問題。

聽起來這是個很複雜的問題,需要各種各樣的調參。

谷歌的 MapReduce 怎麼解決這個問題的呢?Mapper 直接寫進 Google File System。Reducer 直接讀 Google File System。這些 shuffle 文件是不是存在是由 GFS 來管的。

Hadoop 也是這樣做的,但是效果非常的慘烈。因爲 HDFS 作爲一個文件系統性能太差了。而 GFS 不一樣,性能好,尤其是二代 GFS,完全可以當做一個巨大容量的本地盤用。

所以,只要有一個性能很好的分佈式文件系統,shuffle 就不是一個天大的問題。Spark 的 shuffle 搞的如此複雜,問題頻出,各種補救,到底是 Spark 自己的問題還是 Spark 缺了一個高性能的分佈式文件系統來存 shuffle 的文件呢?

谷歌的 MapReduce 很強,其實就強在了谷歌的 GFS 牛逼。到今天看,shuffle 文件寫本地盤,然後硬撐着不死掉讓其他人來讀的設計,實在不知道說什麼了。但是 Spark 根本就沒有一個高性能的分佈式文件系統啊,只能一邊哭,一邊寫本地盤了。

微軟搞 Cosmos 的時候,也是用了自己的分佈式文件系統來解決這個問題的。但是微軟取巧的辦法是數據只寫一份,進本地盤,元數據則直接進元數據服務了。這樣就算 executor 死了,文件大概率並不會丟,只不過只有一份而非三份冗餘。

當然,谷歌文件系統牛逼,不能改變 MapReduce 這個東西本身是屎的本質。Spark 的 shuffle 一直都在苦苦掙扎,也不能改變 Spark 本身計算模型更牛逼的事實。只不過,屎也可以建立在牢固的地基上,牛逼的東西也可以建立在屎堆裏。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/9TWugwDAJJK9UNOBdhbccQ