資料蔣堂|Hadoop中理論與工程的錯位

技術小能手發表於2018-04-02

Hadoop是當前重要的大資料計算平臺,它試圖摒棄傳統資料庫的理念,重新構建一套新的大資料體系。但是,這並不是件很容易的事,在Hadoop的設計和實現中能看到一些先天不足的地方,其中一點就是把理論問題和工程問題給搞擰了。

所謂理論方法,是指試圖解決問題的一般情況,設計通用的演算法能適應儘量多的情況,並努力使演算法的複雜度降低。在研究問題時不會考慮具體環境下某個具體動作是否可以執行以及該動作消耗的資源,而會假想一個理想的環境;工程方法則相反,不需要考慮普遍的一般情況,而是針對某個具體問題,充分利用當前環境提供的便利,並充分考慮每個具體動作消耗的資源(包括時間),儘量高效率低成本地實現目標。原則上,在設計體系模型時要理論化,而在編碼實現時則要工程化,這樣才能做出一個即能解決足夠多問題且效率也可接受的產品。

但是,Hadoop在不少地方把這個事情搞反了。本該由理論解決的一般性問題被用工程方法簡化成特定問題,而具體實現時又把本該在工程層面優化的問題想得過於理論化。導致的結果就是能方便解決的問題太少,而解決問題時效率又太低。一句話說就是理論問題工程化,工程問題理論化

MapReduce是Hadoop中關鍵的並行機制,經過多輪封裝改進,這個模型現在仍然是Hadoop的演算法核心。這個方法認為可以將一個大任務拆成一些無關的小任務,分別處理(Map)後再按某個鍵值歸攏到一起再做處理(Reduce)。Hadoop實現好這個框架後,程式設計師就只要寫Map和Reduce動作即可了,這樣就編寫並行程式就會簡單很多。

MapReduce用來處理求和、計數等簡單問題也確實有效,但世界可沒有這麼簡單!

琢磨一下用MapReduce去實現JOIN運算的麻煩度就知道了(具體做法可以從網上找到,這裡不細說了),而這種有關聯的運算在現實需求中相當常見,其它一些次序有關的運算用MapReduce實現也很困難。也就是說,MapReduce演算法能夠方便描述的運算太少了,這個模型的適應面太窄。基於這個理論實現的產品,面對複雜運算時基本上起不到減少工作量的目標,甚至根本無法應用。本該在理論上研究出更通用的演算法,卻被工程化成簡單情況。

然而,Hadoop在實現MapReduce框架時,卻又缺乏對具體情況的考慮,而是假想了一個理想環境。Hadoop認為叢集節點機可以無窮多,任何效能問題都只要增加節點就可以解決,這樣就沒興趣去關注單機效能了,肆意地跑出多個程式而很少採用經常效率更高(但不總是)的多執行緒手段;Hadoop不考慮外存讀寫的巨大延遲,Map過程 的中間結果要寫盤暫存,理論上覆雜度其實也不算很高(讀寫次數基本是確定的),但實際執行效率之低令人難以容忍,很難想象有工程經驗的程式設計師敢採用這種機制。實測情況是大概四五個節點的hadoop叢集才能趕得上被充分工程優化後的單臺機器效能。

Spark也有類似的問題。Spark前的Hadoop在工程上對記憶體利用不足(如前述的MapReduce總是要落盤),而Spark又走向另一個極端,從理論模型上就只考慮記憶體計算了。我們知道,外存計算和記憶體計算是很不一樣的,外存計算要複雜困難得多,而大資料常常面臨外存計算,原則上我們應當改進當前的外存計算演算法體系,努力降低複雜度並擴大適應範圍,而不是簡單避開這個困難,這就是刻意簡化問題了,適應面會大折折扣。

退一步講,就算只考慮記憶體計算,能做好也是有相當意義的。但是,Spark在實現時卻又走入了理論化的窠臼,它把那個RDD搞成immutable,這個機制有很強的理論色彩,和數學運算中的抽象資料型別一致,用來描述演算法確實很美。可是,實際執行時將造成大量沒有必要的記憶體複製,本來是打算提高效能的,卻得不償失,然後又要再用其它手段去繞。

類似的情況,細糾下去還有。發明新理論確實很難,為降低難度而簡化問題還可以理解(其實傳統資料庫領域已經積累了不少這理論,只是學會並不算很難),但在工程實現時又搞得理論化就難以理解了,這樣怎麼會有高效能?

原文釋出時間為:2018-03-30

本文作者:蔣步星

本文來自雲棲社群合作伙伴“資料派THU”,瞭解相關資訊可以關注“資料派THU”微信公眾號


相關文章