1. 程式人生 > >淺談hadoop工作原理

淺談hadoop工作原理

Hadoop 是一個開源的可運行於大規模叢集上的分散式並行程式設計框架,由於分散式儲存對於分散式程式設計來說是必不可少的,這個框架中還包含了一個分散式檔案系統 HDFS( Hadoop Distributed File System )。也許到目前為止,Hadoop 還不是那麼廣為人知,其最新的版本號也僅僅是 0.16,距離 1.0 似乎都還有很長的一段距離,但提及 Hadoop 一脈相承的另外兩個開源專案 Nutch 和 Lucene ( 三者的創始人都是 Doug Cutting ),那絕對是大名鼎鼎。Lucene 是一個用 Java 開發的開源高效能全文檢索工具包,它不是一個完整的應用程式,而是一套簡單易用的 API 。在全世界範圍內,已有無數的軟體系統,Web 網站基於 Lucene 實現了全文檢索功能,後來 Doug Cutting 又開創了第一個開源的 Web 搜尋引擎( 

http://www.nutch.org ) Nutch, 它在 Lucene 的基礎上增加了網路爬蟲和一些和 Web 相關的功能,一些解析各類文件格式的外掛等,此外,Nutch 中還包含了一個分散式檔案系統用於儲存資料。從 Nutch 0.8.0 版本之後,Doug Cutting 把 Nutch 中的分散式檔案系統以及實現 MapReduce 演算法的程式碼獨立出來形成了一個新的開源項 Hadoop。Nutch 也演化為基於 Lucene 全文檢索以及 Hadoop 分散式計算平臺的一個開源搜尋引擎。

基於 Hadoop,你可以輕鬆地編寫可處理海量資料的分散式並行程式,並將其運行於由成百上千個結點組成的大規模計算機叢集上。從目前的情況來看,Hadoop 註定會有一個輝煌的未來:"雲端計算"是目前灸手可熱的技術名詞,全球各大 IT 公司都在投資和推廣這種新一代的計算模式,而 Hadoop 又被其中幾家主要的公司用作其"雲端計算"環境中的重要基礎軟體,如:雅虎正在藉助 Hadoop 開源平臺的力量對抗 Google, 除了資助 Hadoop 開發團隊外,還在開發基於 Hadoop 的開源專案 Pig, 這是一個專注於海量資料集分析的分散式計算程式。Amazon 公司基於 Hadoop 推出了 Amazon S3 ( Amazon Simple Storage Service ),提供可靠,快速,可擴充套件的網路儲存服務,以及一個商用的雲端計算平臺 Amazon EC2 ( Amazon Elastic Compute Cloud )。在 IBM 公司的雲端計算專案--"藍雲計劃"中,Hadoop 也是其中重要的基礎軟體。Google 正在跟IBM合作,共同推廣基於 Hadoop 的雲端計算。

回頁首

迎接程式設計方式的變革

在摩爾定律的作用下,以前程式設計師根本不用考慮計算機的效能會跟不上軟體的發展,因為約每隔 18 個月,CPU 的主頻就會增加一倍,效能也將提升一倍,軟體根本不用做任何改變,就可以享受免費的效能提升。然而,由於電晶體電路已經逐漸接近其物理上的效能極限,摩爾定律在 2005 年左右開始失效了,人類再也不能期待單個 CPU 的速度每隔 18 個月就翻一倍,為我們提供越來越快的計算效能。Intel, AMD, IBM 等晶片廠商開始從多核這個角度來挖掘 CPU 的效能潛力,多核時代以及網際網路時代的到來,將使軟體程式設計方式發生重大變革,基於多核的多執行緒併發程式設計以及基於大規模計算機叢集的分散式並行程式設計是將來軟體效能提升的主要途徑。

許多人認為這種程式設計方式的重大變化將帶來一次軟體的併發危機,因為我們傳統的軟體方式基本上是單指令單資料流的順序執行,這種順序執行十分符合人類的思考習慣,卻與併發並行程式設計格格不入。基於叢集的分散式並行程式設計能夠讓軟體與資料同時執行在連成一個網路的許多臺計算機上,這裡的每一臺計算機均可以是一臺普通的 PC 機。這樣的分散式並行環境的最大優點是可以很容易的通過增加計算機來擴充新的計算結點,並由此獲得不可思議的海量計算能力, 同時又具有相當強的容錯能力,一批計算結點失效也不會影響計算的正常進行以及結果的正確性。Google 就是這麼做的,他們使用了叫做 MapReduce 的並行程式設計模型進行分散式並行程式設計,執行在叫做 GFS ( Google File System )的分散式檔案系統上,為全球億萬使用者提供搜尋服務。

Hadoop 實現了 Google 的 MapReduce 程式設計模型,提供了簡單易用的程式設計介面,也提供了它自己的分散式檔案系統 HDFS,與 Google 不同的是,Hadoop 是開源的,任何人都可以使用這個框架來進行並行程式設計。如果說分散式並行程式設計的難度足以讓普通程式設計師望而生畏的話,開源的 Hadoop 的出現極大的降低了它的門檻,讀完本文,你會發現基於 Hadoop 程式設計非常簡單,無須任何並行開發經驗,你也可以輕鬆的開發出分散式的並行程式,並讓其令人難以置信地同時執行在數百臺機器上,然後在短時間內完成海量資料的計算。你可能會覺得你不可能會擁有數百臺機器來執行你的並行程式,而事實上,隨著"雲端計算"的普及,任何人都可以輕鬆獲得這樣的海量計算能力。 例如現在 Amazon 公司的雲端計算平臺 Amazon EC2 已經提供了這種按需計算的租用服務,有興趣的讀者可以去了解一下,這篇系列文章的第三部分將有所介紹。

掌握一點分散式並行程式設計的知識對將來的程式設計師是必不可少的,Hadoop 是如此的簡便好用,何不嘗試一下呢?也許你已經急不可耐的想試一下基於 Hadoop 的程式設計是怎麼回事了,但畢竟這種程式設計模型與傳統的順序程式大不相同,掌握一點基礎知識才能更好地理解基於 Hadoop 的分散式並行程式是如何編寫和執行的。因此本文會先介紹一下 MapReduce 的計算模型,Hadoop 中的分散式檔案系統 HDFS, Hadoop 是如何實現平行計算的,然後才介紹如何安裝和部署 Hadoop 框架,以及如何執行 Hadoop 程式。

回頁首

MapReduce 計算模型

MapReduce 是 Google 公司的核心計算模型,它將複雜的運行於大規模叢集上的平行計算過程高度的抽象到了兩個函式,Map 和 Reduce, 這是一個令人驚訝的簡單卻又威力巨大的模型。適合用 MapReduce 來處理的資料集(或任務)有一個基本要求: 待處理的資料集可以分解成許多小的資料集,而且每一個小資料集都可以完全並行地進行處理。


圖 1. MapReduce 計算流程 
MapReduce 計算流程

圖一說明了用 MapReduce 來處理大資料集的過程, 這個 MapReduce 的計算過程簡而言之,就是將大資料集分解為成百上千的小資料集,每個(或若干個)資料集分別由叢集中的一個結點(一般就是一臺普通的計算機)進行處理並生成中間結果,然後這些中間結果又由大量的結點進行合併, 形成最終結果。

計算模型的核心是 Map 和 Reduce 兩個函式,這兩個函式由使用者負責實現,功能是按一定的對映規則將輸入的 <key, value> 對轉換成另一個或一批 <key, value> 對輸出。


表一 Map 和 Reduce 函式

函式 輸入 輸出 說明
Map <k1, v1> List(<k2,v2>) 1. 將小資料集進一步解析成一批 <key,value> 對,輸入 Map 函式中進行處理。 
2. 每一個輸入的 <k1,v1> 會輸出一批 <k2,v2>。 <k2,v2> 是計算的中間結果。
Reduce <k2,List(v2)> <k3,v3> 輸入的中間結果 <k2,List(v2)> 中的 List(v2) 表示是一批屬於同一個 k2 的 value

以一個計算文字檔案中每個單詞出現的次數的程式為例,<k1,v1> 可以是 <行在檔案中的偏移位置, 檔案中的一行>,經 Map 函式對映之後,形成一批中間結果 <單詞,出現次數>, 而 Reduce 函式則可以對中間結果進行處理,將相同單詞的出現次數進行累加,得到每個單詞的總的出現次數。

基於 MapReduce 計算模型編寫分散式並行程式非常簡單,程式設計師的主要編碼工作就是實現 Map 和 Reduce 函式,其它的並行程式設計中的種種複雜問題,如分散式儲存,工作排程,負載平衡,容錯處理,網路通訊等,均由 MapReduce 框架(比如 Hadoop )負責處理,程式設計師完全不用操心。

回頁首

四 叢集上的平行計算

MapReduce 計算模型非常適合在大量計算機組成的大規模叢集上並行執行。圖一中的每一個 Map 任務和每一個 Reduce 任務均可以同時運行於一個單獨的計算結點上,可想而知其運算效率是很高的,那麼這樣的平行計算是如何做到的呢?

資料分佈儲存

Hadoop 中的分散式檔案系統 HDFS 由一個管理結點 ( NameNode )和N個數據結點 ( DataNode )組成,每個結點均是一臺普通的計算機。在使用上同我們熟悉的單機上的檔案系統非常類似,一樣可以建目錄,建立,複製,刪除檔案,檢視檔案內容等。但其底層實現上是把檔案切割成 Block,然後這些 Block 分散地儲存於不同的 DataNode 上,每個 Block 還可以複製數份儲存於不同的 DataNode 上,達到容錯容災之目的。NameNode 則是整個 HDFS 的核心,它通過維護一些資料結構,記錄了每一個檔案被切割成了多少個 Block,這些 Block 可以從哪些 DataNode 中獲得,各個 DataNode 的狀態等重要資訊。如果你想了解更多的關於 HDFS 的資訊,可進一步閱讀參考資料:  The Hadoop Distributed File System:Architecture and Design

分散式平行計算

Hadoop 中有一個作為主控的 JobTracker,用於排程和管理其它的 TaskTracker, JobTracker 可以運行於叢集中任一臺計算機上。TaskTracker 負責執行任務,必須運行於 DataNode 上,即 DataNode 既是資料儲存結點,也是計算結點。 JobTracker 將 Map 任務和 Reduce 任務分發給空閒的 TaskTracker, 讓這些任務並行執行,並負責監控任務的執行情況。如果某一個 TaskTracker 出故障了,JobTracker 會將其負責的任務轉交給另一個空閒的 TaskTracker 重新執行。

本地計算

資料儲存在哪一臺計算機上,就由這臺計算機進行這部分資料的計算,這樣可以減少資料在網路上的傳輸,降低對網路頻寬的需求。在 Hadoop 這樣的基於叢集的分散式並行系統中,計算結點可以很方便地擴充,而因它所能夠提供的計算能力近乎是無限的,但是由是資料需要在不同的計算機之間流動,故網路頻寬變成了瓶頸,是非常寶貴的,“本地計算”是最有效的一種節約網路頻寬的手段,業界把這形容為“移動計算比移動資料更經濟”。


圖 2. 分佈儲存與平行計算 
分佈儲存與平行計算

任務粒度

把原始大資料集切割成小資料集時,通常讓小資料集小於或等於 HDFS 中一個 Block 的大小(預設是 64M),這樣能夠保證一個小資料集位於一臺計算機上,便於本地計算。有 M 個小資料集待處理,就啟動 M 個 Map 任務,注意這 M 個 Map 任務分佈於 N 臺計算機上並行執行,Reduce 任務的數量 R 則可由使用者指定。

Partition

把 Map 任務輸出的中間結果按 key 的範圍劃分成 R 份( R 是預先定義的 Reduce 任務的個數),劃分時通常使用 hash 函式如: hash(key) mod R,這樣可以保證某一段範圍內的 key,一定是由一個 Reduce 任務來處理,可以簡化 Reduce 的過程。

Combine

在 partition 之前,還可以對中間結果先做 combine,即將中間結果中有相同 key的 <key, value> 對合併成一對。combine 的過程與 Reduce 的過程類似,很多情況下就可以直接使用 Reduce 函式,但 combine 是作為 Map 任務的一部分,在執行完 Map 函式後緊接著執行的。Combine 能夠減少中間結果中 <key, value> 對的數目,從而減少網路流量。

Reduce 任務從 Map 任務結點取中間結果

Map 任務的中間結果在做完 Combine 和 Partition 之後,以檔案形式存於本地磁碟。中間結果檔案的位置會通知主控 JobTracker, JobTracker 再通知 Reduce 任務到哪一個 DataNode 上去取中間結果。注意所有的 Map 任務產生中間結果均按其 Key 用同一個 Hash 函式劃分成了 R 份,R 個 Reduce 任務各自負責一段 Key 區間。每個 Reduce 需要向許多個 Map 任務結點取得落在其負責的 Key 區間內的中間結果,然後執行 Reduce 函式,形成一個最終的結果檔案。

任務管道

有 R 個 Reduce 任務,就會有 R 個最終結果,很多情況下這 R 個最終結果並不需要合併成一個最終結果。因為這 R 個最終結果又可以做為另一個計算任務的輸入,開始另一個平行計算任務。