Hadoop中理論與工程的錯位
Hadoop是當(dāng)前重要的大數(shù)據(jù)計算平臺,它試圖摒棄傳統(tǒng)數(shù)據(jù)庫的理念,重新構(gòu)建一套新的大數(shù)據(jù)體系。但是,這并不是件很容易的事,在Hadoop的設(shè)計和實現(xiàn)中能看到一些先天不足的地方,其中一點就是把理論問題和工程問題給搞擰了。
所謂理論方法,是指試圖解決問題的一般情況,設(shè)計通用的算法能適應(yīng)盡量多的情況,并努力使算法的復(fù)雜度降低。在研究問題時不會考慮具體環(huán)境下某個具體動作是否可以執(zhí)行以及該動作消耗的資源,而會假想一個理想的環(huán)境;工程方法則相反,不需要考慮普遍的一般情況,而是針對某個具體問題,充分利用當(dāng)前環(huán)境提供的便利,并充分考慮每個具體動作消耗的資源(包括時間),盡量高效率低成本地實現(xiàn)目標(biāo)。原則上,在設(shè)計體系模型時要理論化,而在編碼實現(xiàn)時則要工程化,這樣才能做出一個即能解決足夠多問題且效率也可接受的產(chǎn)品。
但是,Hadoop在不少地方把這個事情搞反了。本該由理論解決的一般性問題被用工程方法簡化成特定問題,而具體實現(xiàn)時又把本該在工程層面優(yōu)化的問題想得過于理論化。導(dǎo)致的結(jié)果就是能方便解決的問題太少,而解決問題時效率又太低。一句話說就是理論問題工程化,工程問題理論化。
MapReduce是Hadoop中關(guān)鍵的并行機(jī)制,經(jīng)過多輪封裝改進(jìn),這個模型現(xiàn)在仍然是Hadoop的算法核心。這個方法認(rèn)為可以將一個大任務(wù)拆成一些無關(guān)的小任務(wù),分別處理(Map)后再按某個鍵值歸攏到一起再做處理(Reduce)。Hadoop實現(xiàn)好這個框架后,程序員就只要寫Map和Reduce動作即可了,這樣就編寫并行程序就會簡單很多。
MapReduce用來處理求和、計數(shù)等簡單問題也確實有效,但世界可沒有這么簡單!
琢磨一下用MapReduce去實現(xiàn)JOIN運(yùn)算的麻煩度就知道了(具體做法可以從網(wǎng)上找到,這里不細(xì)說了),而這種有關(guān)聯(lián)的運(yùn)算在現(xiàn)實需求中相當(dāng)常見,其它一些次序有關(guān)的運(yùn)算用MapReduce實現(xiàn)也很困難。也就是說,MapReduce算法能夠方便描述的運(yùn)算太少了,這個模型的適應(yīng)面太窄?;谶@個理論實現(xiàn)的產(chǎn)品,面對復(fù)雜運(yùn)算時基本上起不到減少工作量的目標(biāo),甚至根本無法應(yīng)用。本該在理論上研究出更通用的算法,卻被工程化成簡單情況。
然而,Hadoop在實現(xiàn)MapReduce框架時,卻又缺乏對具體情況的考慮,而是假想了一個理想環(huán)境。Hadoop認(rèn)為集群節(jié)點機(jī)可以無窮多,任何性能問題都只要增加節(jié)點就可以解決,這樣就沒興趣去關(guān)注單機(jī)性能了,肆意地跑出多個進(jìn)程而很少采用經(jīng)常效率更高(但不總是)的多線程手段;Hadoop不考慮外存讀寫的巨大延遲,Map過程 的中間結(jié)果要寫盤暫存,理論上復(fù)雜度其實也不算很高(讀寫次數(shù)基本是確定的),但實際運(yùn)行效率之低令人難以容忍,很難想象有工程經(jīng)驗的程序員敢采用這種機(jī)制。實測情況是大概四五個節(jié)點的hadoop集群才能趕得上被充分工程優(yōu)化后的單臺機(jī)器性能。
Spark也有類似的問題。Spark前的Hadoop在工程上對內(nèi)存利用不足(如前述的MapReduce總是要落盤),而Spark又走向另一個極端,從理論模型上就只考慮內(nèi)存計算了。我們知道,外存計算和內(nèi)存計算是很不一樣的,外存計算要復(fù)雜困難得多,而大數(shù)據(jù)常常面臨外存計算,原則上我們應(yīng)當(dāng)改進(jìn)當(dāng)前的外存計算算法體系,努力降低復(fù)雜度并擴(kuò)大適應(yīng)范圍,而不是簡單避開這個困難,這就是刻意簡化問題了,適應(yīng)面會大折折扣。
退一步講,就算只考慮內(nèi)存計算,能做好也是有相當(dāng)意義的。但是,Spark在實現(xiàn)時卻又走入了理論化的窠臼,它把那個RDD搞成immutable,這個機(jī)制有很強(qiáng)的理論色彩,和數(shù)學(xué)運(yùn)算中的抽象數(shù)據(jù)類型一致,用來描述算法確實很美??墒?,實際運(yùn)行時將造成大量沒有必要的內(nèi)存復(fù)制,本來是打算提高性能的,卻得不償失,然后又要再用其它手段去繞。
類似的情況,細(xì)糾下去還有。發(fā)明新理論確實很難,為降低難度而簡化問題還可以理解(其實傳統(tǒng)數(shù)據(jù)庫領(lǐng)域已經(jīng)積累了不少這理論,只是學(xué)會并不算很難),但在工程實現(xiàn)時又搞得理論化就難以理解了,這樣怎么會有高性能?