Hadoop 是一個(gè)實(shí)現(xiàn)了 MapReduce 計(jì)算模型的開(kāi)源分布式并行編程框架,借助于 Hadoop,
程序員可以輕松地編寫(xiě)分布式并行程序,將其運(yùn)行于計(jì)算機(jī)集群上,完成海量數(shù)據(jù)的計(jì)算。本文將介紹 MapReduce
計(jì)算模型,分布式并行計(jì)算等基本概念,以及 Hadoop 的安裝部署和基本運(yùn)行方法。
Hadoop 簡(jiǎn)介
Hadoop
是一個(gè)開(kāi)源的可運(yùn)行于大規(guī)模集群上的分布式并行編程框架,由于分布式存儲(chǔ)對(duì)于分布式編程來(lái)說(shuō)是必不可少的,這個(gè)框架中還包含了一個(gè)分布式文件系統(tǒng)
HDFS( Hadoop Distributed File System )。也許到目前為止,Hadoop
還不是那么廣為人知,其最新的版本號(hào)也僅僅是 0.16,距離 1.0 似乎都還有很長(zhǎng)的一段距離,但提及 Hadoop 一脈相承的另外兩個(gè)開(kāi)源項(xiàng)目
Nutch 和 Lucene ( 三者的創(chuàng)始人都是 Doug Cutting ),那絕對(duì)是大名鼎鼎。Lucene 是一個(gè)用 Java
開(kāi)發(fā)的開(kāi)源高性能全文檢索工具包,它不是一個(gè)完整的應(yīng)用程序,而是一套簡(jiǎn)單易用的 API 。在全世界范圍內(nèi),已有無(wú)數(shù)的軟件系統(tǒng),Web 網(wǎng)站基于
Lucene 實(shí)現(xiàn)了全文檢索功能,后來(lái) Doug Cutting 又開(kāi)創(chuàng)了第一個(gè)開(kāi)源的 Web 搜索引擎(
http://www.nutch.org)
Nutch, 它在 Lucene 的基礎(chǔ)上增加了網(wǎng)絡(luò)爬蟲(chóng)和一些和 Web 相關(guān)的功能,一些解析各類文檔格式的插件等,此外,Nutch
中還包含了一個(gè)分布式文件系統(tǒng)用于存儲(chǔ)數(shù)據(jù)。從 Nutch 0.8.0 版本之后,Doug Cutting 把 Nutch
中的分布式文件系統(tǒng)以及實(shí)現(xiàn) MapReduce 算法的代碼獨(dú)立出來(lái)形成了一個(gè)新的開(kāi)源項(xiàng) Hadoop。Nutch 也演化為基于 Lucene
全文檢索以及 Hadoop 分布式計(jì)算平臺(tái)的一個(gè)開(kāi)源搜索引擎。
基于
Hadoop,你可以輕松地編寫(xiě)可處理海量數(shù)據(jù)的分布式并行程序,并將其運(yùn)行于由成百上千個(gè)結(jié)點(diǎn)組成的大規(guī)模計(jì)算機(jī)集群上。從目前的情況來(lái)
看,Hadoop 注定會(huì)有一個(gè)輝煌的未來(lái):"云計(jì)算"是目前灸手可熱的技術(shù)名詞,全球各大 IT 公司都在投資和推廣這種新一代的計(jì)算模式,而
Hadoop 又被其中幾家主要的公司用作其"云計(jì)算"環(huán)境中的重要基礎(chǔ)軟件,如:雅虎正在借助 Hadoop 開(kāi)源平臺(tái)的力量對(duì)抗 Google,
除了資助 Hadoop 開(kāi)發(fā)團(tuán)隊(duì)外,還在開(kāi)發(fā)基于 Hadoop 的開(kāi)源項(xiàng)目 Pig, 這是一個(gè)專注于海量數(shù)據(jù)集分析的分布式計(jì)算程序。Amazon
公司基于 Hadoop 推出了 Amazon S3 ( Amazon Simple Storage Service
),提供可靠,快速,可擴(kuò)展的網(wǎng)絡(luò)存儲(chǔ)服務(wù),以及一個(gè)商用的云計(jì)算平臺(tái) Amazon EC2 ( Amazon Elastic Compute
Cloud )。在 IBM 公司的云計(jì)算項(xiàng)目--"藍(lán)云計(jì)劃"中,Hadoop 也是其中重要的基礎(chǔ)軟件。Google
正在跟IBM合作,共同推廣基于 Hadoop 的云計(jì)算。
迎接編程方式的變革
在摩爾定律的作用下,以前程序員根本不用考慮計(jì)算機(jī)的性能會(huì)跟不上軟件的發(fā)展,因?yàn)榧s每隔 18 個(gè)月,CPU
的主頻就會(huì)增加一倍,性能也將提升一倍,軟件根本不用做任何改變,就可以享受免費(fèi)的性能提升。然而,由于晶體管電路已經(jīng)逐漸接近其物理上的性能極限,摩爾
定律在 2005 年左右開(kāi)始失效了,人類再也不能期待單個(gè) CPU 的速度每隔 18 個(gè)月就翻一倍,為我們提供越來(lái)越快的計(jì)算性能。Intel,
AMD, IBM 等芯片廠商開(kāi)始從多核這個(gè)角度來(lái)挖掘 CPU
的性能潛力,多核時(shí)代以及互聯(lián)網(wǎng)時(shí)代的到來(lái),將使軟件編程方式發(fā)生重大變革,基于多核的多線程并發(fā)編程以及基于大規(guī)模計(jì)算機(jī)集群的分布式并行編程是將來(lái)軟
件性能提升的主要途徑。
許多人認(rèn)為這種編程方式的重大變化將帶來(lái)一次軟件的并發(fā)危機(jī),因?yàn)槲覀儌鹘y(tǒng)的軟件方式基本上是單指令單數(shù)據(jù)流的順序執(zhí)行,這種順序執(zhí)行十分符合人
類的思考習(xí)慣,卻與并發(fā)并行編程格格不入。基于集群的分布式并行編程能夠讓軟件與數(shù)據(jù)同時(shí)運(yùn)行在連成一個(gè)網(wǎng)絡(luò)的許多臺(tái)計(jì)算機(jī)上,這里的每一臺(tái)計(jì)算機(jī)均可以
是一臺(tái)普通的 PC 機(jī)。這樣的分布式并行環(huán)境的最大優(yōu)點(diǎn)是可以很容易的通過(guò)增加計(jì)算機(jī)來(lái)擴(kuò)充新的計(jì)算結(jié)點(diǎn),并由此獲得不可思議的海量計(jì)算能力,
同時(shí)又具有相當(dāng)強(qiáng)的容錯(cuò)能力,一批計(jì)算結(jié)點(diǎn)失效也不會(huì)影響計(jì)算的正常進(jìn)行以及結(jié)果的正確性。Google 就是這么做的,他們使用了叫做
MapReduce 的并行編程模型進(jìn)行分布式并行編程,運(yùn)行在叫做 GFS ( Google File System
)的分布式文件系統(tǒng)上,為全球億萬(wàn)用戶提供搜索服務(wù)。
Hadoop 實(shí)現(xiàn)了 Google 的 MapReduce 編程模型,提供了簡(jiǎn)單易用的編程接口,也提供了它自己的分布式文件系統(tǒng)
HDFS,與 Google 不同的是,Hadoop
是開(kāi)源的,任何人都可以使用這個(gè)框架來(lái)進(jìn)行并行編程。如果說(shuō)分布式并行編程的難度足以讓普通程序員望而生畏的話,開(kāi)源的 Hadoop
的出現(xiàn)極大的降低了它的門(mén)檻,讀完本文,你會(huì)發(fā)現(xiàn)基于 Hadoop
編程非常簡(jiǎn)單,無(wú)須任何并行開(kāi)發(fā)經(jīng)驗(yàn),你也可以輕松的開(kāi)發(fā)出分布式的并行程序,并讓其令人難以置信地同時(shí)運(yùn)行在數(shù)百臺(tái)機(jī)器上,然后在短時(shí)間內(nèi)完成海量數(shù)據(jù)
的計(jì)算。你可能會(huì)覺(jué)得你不可能會(huì)擁有數(shù)百臺(tái)機(jī)器來(lái)運(yùn)行你的并行程序,而事實(shí)上,隨著"云計(jì)算"的普及,任何人都可以輕松獲得這樣的海量計(jì)算能力。例如現(xiàn)在
Amazon 公司的云計(jì)算平臺(tái) Amazon EC2
已經(jīng)提供了這種按需計(jì)算的租用服務(wù),有興趣的讀者可以去了解一下,這篇系列文章的第三部分將有所介紹。
掌握一點(diǎn)分布式并行編程的知識(shí)對(duì)將來(lái)的程序員是必不可少的,Hadoop 是如此的簡(jiǎn)便好用,何不嘗試一下呢?也許你已經(jīng)急不可耐的想試一下基于
Hadoop 的編程是怎么回事了,但畢竟這種編程模型與傳統(tǒng)的順序程序大不相同,掌握一點(diǎn)基礎(chǔ)知識(shí)才能更好地理解基于 Hadoop
的分布式并行程序是如何編寫(xiě)和運(yùn)行的。因此本文會(huì)先介紹一下 MapReduce 的計(jì)算模型,Hadoop 中的分布式文件系統(tǒng) HDFS,
Hadoop 是如何實(shí)現(xiàn)并行計(jì)算的,然后才介紹如何安裝和部署 Hadoop 框架,以及如何運(yùn)行 Hadoop 程序。
MapReduce 計(jì)算模型
MapReduce 是 Google 公司的核心計(jì)算模型,它將復(fù)雜的運(yùn)行于大規(guī)模集群上的并行計(jì)算過(guò)程高度的抽象到了兩個(gè)函數(shù),Map 和
Reduce, 這是一個(gè)令人驚訝的簡(jiǎn)單卻又威力巨大的模型。適合用 MapReduce 來(lái)處理的數(shù)據(jù)集(或任務(wù))有一個(gè)基本要求:
待處理的數(shù)據(jù)集可以分解成許多小的數(shù)據(jù)集,而且每一個(gè)小數(shù)據(jù)集都可以完全并行地進(jìn)行處理。
圖 1. MapReduce 計(jì)算流程
圖一說(shuō)明了用 MapReduce 來(lái)處理大數(shù)據(jù)集的過(guò)程, 這個(gè) MapReduce
的計(jì)算過(guò)程簡(jiǎn)而言之,就是將大數(shù)據(jù)集分解為成百上千的小數(shù)據(jù)集,每個(gè)(或若干個(gè))數(shù)據(jù)集分別由集群中的一個(gè)結(jié)點(diǎn)(一般就是一臺(tái)普通的計(jì)算機(jī))進(jìn)行處理并生
成中間結(jié)果,然后這些中間結(jié)果又由大量的結(jié)點(diǎn)進(jìn)行合并, 形成最終結(jié)果。
計(jì)算模型的核心是 Map 和 Reduce 兩個(gè)函數(shù),這兩個(gè)函數(shù)由用戶負(fù)責(zé)實(shí)現(xiàn),功能是按一定的映射規(guī)則將輸入的 <key, value> 對(duì)轉(zhuǎn)換成另一個(gè)或一批 <key, value> 對(duì)輸出。
表一 Map 和 Reduce 函數(shù)
函數(shù) 輸入 輸出 說(shuō)明
Map <k1, v1> List(<k2,v2>) 1. 將小數(shù)據(jù)集進(jìn)一步解析成一批 <key,value> 對(duì),輸入 Map 函數(shù)中進(jìn)行處理。
2. 每一個(gè)輸入的 <k1,v1> 會(huì)輸出一批 <k2,v2>。 <k2,v2> 是計(jì)算的中間結(jié)果。
Reduce <k2,List(v2)> <k3,v3> 輸入的中間結(jié)果 <k2,List(v2)> 中的 List(v2) 表示是一批屬于同一個(gè) k2 的 value
以一個(gè)計(jì)算文本文件中每個(gè)單詞出現(xiàn)的次數(shù)的程序?yàn)槔?lt;k1,v1> 可以是 <行在文件中的偏移位置,
文件中的一行>,經(jīng) Map 函數(shù)映射之后,形成一批中間結(jié)果 <單詞,出現(xiàn)次數(shù)>, 而 Reduce
函數(shù)則可以對(duì)中間結(jié)果進(jìn)行處理,將相同單詞的出現(xiàn)次數(shù)進(jìn)行累加,得到每個(gè)單詞的總的出現(xiàn)次數(shù)。
基于 MapReduce 計(jì)算模型編寫(xiě)分布式并行程序非常簡(jiǎn)單,程序員的主要編碼工作就是實(shí)現(xiàn) Map 和 Reduce
函數(shù),其它的并行編程中的種種復(fù)雜問(wèn)題,如分布式存儲(chǔ),工作調(diào)度,負(fù)載平衡,容錯(cuò)處理,網(wǎng)絡(luò)通信等,均由 MapReduce 框架(比如 Hadoop
)負(fù)責(zé)處理,程序員完全不用操心。
四 集群上的并行計(jì)算
MapReduce 計(jì)算模型非常適合在大量計(jì)算機(jī)組成的大規(guī)模集群上并行運(yùn)行。圖一中的每一個(gè) Map 任務(wù)和每一個(gè) Reduce 任務(wù)均可以同時(shí)運(yùn)行于一個(gè)單獨(dú)的計(jì)算結(jié)點(diǎn)上,可想而知其運(yùn)算效率是很高的,那么這樣的并行計(jì)算是如何做到的呢?
數(shù)據(jù)分布存儲(chǔ)
Hadoop 中的分布式文件系統(tǒng) HDFS 由一個(gè)管理結(jié)點(diǎn) ( NameNode )和N個(gè)數(shù)據(jù)結(jié)點(diǎn) ( DataNode
)組成,每個(gè)結(jié)點(diǎn)均是一臺(tái)普通的計(jì)算機(jī)。在使用上同我們熟悉的單機(jī)上的文件系統(tǒng)非常類似,一樣可以建目錄,創(chuàng)建,復(fù)制,刪除文件,查看文件內(nèi)容等。但其底
層實(shí)現(xiàn)上是把文件切割成 Block,然后這些 Block 分散地存儲(chǔ)于不同的 DataNode 上,每個(gè) Block 還可以復(fù)制數(shù)份存儲(chǔ)于不同的
DataNode 上,達(dá)到容錯(cuò)容災(zāi)之目的。NameNode 則是整個(gè) HDFS
的核心,它通過(guò)維護(hù)一些數(shù)據(jù)結(jié)構(gòu),記錄了每一個(gè)文件被切割成了多少個(gè) Block,這些 Block 可以從哪些 DataNode 中獲得,各個(gè)
DataNode 的狀態(tài)等重要信息。如果你想了解更多的關(guān)于 HDFS 的信息,可進(jìn)一步閱讀參考資料: [url]The Hadoop
Distributed File System:Architecture and Design [/url]
分布式并行計(jì)算
Hadoop 中有一個(gè)作為主控的 JobTracker,用于調(diào)度和管理其它的 TaskTracker, JobTracker
可以運(yùn)行于集群中任一臺(tái)計(jì)算機(jī)上。TaskTracker 負(fù)責(zé)執(zhí)行任務(wù),必須運(yùn)行于 DataNode 上,即 DataNode
既是數(shù)據(jù)存儲(chǔ)結(jié)點(diǎn),也是計(jì)算結(jié)點(diǎn)。 JobTracker 將 Map 任務(wù)和 Reduce 任務(wù)分發(fā)給空閑的 TaskTracker,
讓這些任務(wù)并行運(yùn)行,并負(fù)責(zé)監(jiān)控任務(wù)的運(yùn)行情況。如果某一個(gè) TaskTracker 出故障了,JobTracker
會(huì)將其負(fù)責(zé)的任務(wù)轉(zhuǎn)交給另一個(gè)空閑的 TaskTracker 重新運(yùn)行。
本地計(jì)算
數(shù)據(jù)存儲(chǔ)在哪一臺(tái)計(jì)算機(jī)上,就由這臺(tái)計(jì)算機(jī)進(jìn)行這部分?jǐn)?shù)據(jù)的計(jì)算,這樣可以減少數(shù)據(jù)在網(wǎng)絡(luò)上的傳輸,降低對(duì)網(wǎng)絡(luò)帶寬的需求。在 Hadoop
這樣的基于集群的分布式并行系統(tǒng)中,計(jì)算結(jié)點(diǎn)可以很方便地?cái)U(kuò)充,而因它所能夠提供的計(jì)算能力近乎是無(wú)限的,但是由是數(shù)據(jù)需要在不同的計(jì)算機(jī)之間流動(dòng),故網(wǎng)
絡(luò)帶寬變成了瓶頸,是非常寶貴的,“本地計(jì)算”是最有效的一種節(jié)約網(wǎng)絡(luò)帶寬的手段,業(yè)界把這形容為“移動(dòng)計(jì)算比移動(dòng)數(shù)據(jù)更經(jīng)濟(jì)”。
圖 2. 分布存儲(chǔ)與并行計(jì)算
任務(wù)粒度
把原始大數(shù)據(jù)集切割成小數(shù)據(jù)集時(shí),通常讓小數(shù)據(jù)集小于或等于 HDFS 中一個(gè) Block 的大小(缺省是
64M),這樣能夠保證一個(gè)小數(shù)據(jù)集位于一臺(tái)計(jì)算機(jī)上,便于本地計(jì)算。有 M 個(gè)小數(shù)據(jù)集待處理,就啟動(dòng) M 個(gè) Map 任務(wù),注意這 M 個(gè) Map
任務(wù)分布于 N 臺(tái)計(jì)算機(jī)上并行運(yùn)行,Reduce 任務(wù)的數(shù)量 R 則可由用戶指定。
Partition
把 Map 任務(wù)輸出的中間結(jié)果按 key 的范圍劃分成 R 份( R 是預(yù)先定義的 Reduce 任務(wù)的個(gè)數(shù)),劃分時(shí)通常使用 hash
函數(shù)如: hash(key) mod R,這樣可以保證某一段范圍內(nèi)的 key,一定是由一個(gè) Reduce 任務(wù)來(lái)處理,可以簡(jiǎn)化 Reduce
的過(guò)程。
Combine
在 partition 之前,還可以對(duì)中間結(jié)果先做 combine,即將中間結(jié)果中有相同 key的 <key, value>
對(duì)合并成一對(duì)。combine 的過(guò)程與 Reduce 的過(guò)程類似,很多情況下就可以直接使用 Reduce 函數(shù),但 combine 是作為
Map 任務(wù)的一部分,在執(zhí)行完 Map 函數(shù)后緊接著執(zhí)行的。Combine 能夠減少中間結(jié)果中 <key, value>
對(duì)的數(shù)目,從而減少網(wǎng)絡(luò)流量。
Reduce 任務(wù)從 Map 任務(wù)結(jié)點(diǎn)取中間結(jié)果
Map 任務(wù)的中間結(jié)果在做完 Combine 和 Partition 之后,以文件形式存于本地磁盤(pán)。中間結(jié)果文件的位置會(huì)通知主控
JobTracker, JobTracker 再通知 Reduce 任務(wù)到哪一個(gè) DataNode 上去取中間結(jié)果。注意所有的 Map
任務(wù)產(chǎn)生中間結(jié)果均按其 Key 用同一個(gè) Hash 函數(shù)劃分成了 R 份,R 個(gè) Reduce 任務(wù)各自負(fù)責(zé)一段 Key 區(qū)間。每個(gè)
Reduce 需要向許多個(gè) Map 任務(wù)結(jié)點(diǎn)取得落在其負(fù)責(zé)的 Key 區(qū)間內(nèi)的中間結(jié)果,然后執(zhí)行 Reduce 函數(shù),形成一個(gè)最終的結(jié)果文件。
任務(wù)管道
有 R 個(gè) Reduce 任務(wù),就會(huì)有 R 個(gè)最終結(jié)果,很多情況下這 R 個(gè)最終結(jié)果并不需要合并成一個(gè)最終結(jié)果。因?yàn)檫@ R 個(gè)最終結(jié)果又可以做為另一個(gè)計(jì)算任務(wù)的輸入,開(kāi)始另一個(gè)并行計(jì)算任務(wù)。
五 Hadoop 初體驗(yàn)
Hadoop 支持 Linux 及 Windows 操作系統(tǒng), 但其官方網(wǎng)站聲明 Hadoop 的分布式操作在 Windows
上未做嚴(yán)格測(cè)試,建議只把 Windows 作為 Hadoop 的開(kāi)發(fā)平臺(tái)。在 Windows 環(huán)境上的安裝步驟如下( Linux
平臺(tái)類似,且更簡(jiǎn)單一些):
(1)在 Windows 下,需要先安裝 Cgywin, 安裝 Cgywin 時(shí)注意一定要選擇安裝 openssh (在 Net
category )。安裝完成之后,把 Cgywin 的安裝目錄如 c:\cygwin\bin 加到系統(tǒng)環(huán)境變量 PATH 中,這是因?yàn)檫\(yùn)行
Hadoop 要執(zhí)行一些 linux 環(huán)境下的腳本和命令。
(2)安裝 Java 1.5.x,并將 JAVA_HOME 環(huán)境變量設(shè)置為 Java 的安裝根目錄如 C:\Program Files\Java\jdk1.5.0_01。
(3)到 Hadoop 官方網(wǎng)站[url] http://hadoop.apache.org[/url]下載Hadoop Core, 最新的穩(wěn)定版本是 0.16.0. 將下載后的安裝包解壓到一個(gè)目錄,本文假定解壓到 c:\hadoop-0.16.0。
4)修改 conf/hadoop-env.sh 文件,在其中設(shè)置 JAVA_HOME 環(huán)境變量: export
JAVA_HOME="C:\Program Files\Java\jdk1.5.0_01” (因?yàn)槁窂街?Program Files
中間有空格,一定要用雙引號(hào)將路徑引起來(lái))
至此,一切就緒,可以運(yùn)行 Hadoop 了。以下的運(yùn)行過(guò)程,需要啟動(dòng) cygwin, 進(jìn)入模擬 Linux 環(huán)境。在下載的 Hadoop
Core 包中,帶有幾個(gè)示例程序并且已經(jīng)打包成了 hadoop-0.16.0-examples.jar。其中有一個(gè) WordCount
程序,功能是統(tǒng)計(jì)一批文本文件中各個(gè)單詞出現(xiàn)的次數(shù),我們先來(lái)看看怎么運(yùn)行這個(gè)程序。Hadoop 共有三種運(yùn)行模式:
單機(jī)(非分布式)模式,偽分布式運(yùn)行模式,分布式運(yùn)行模式,其中前兩種運(yùn)行模式體現(xiàn)不了 Hadoop
分布式計(jì)算的優(yōu)勢(shì),并沒(méi)有什么實(shí)際意義,但對(duì)程序的測(cè)試及調(diào)試很有幫助,我們先從這兩種模式入手,了解基于 Hadoop
的分布式并行程序是如何編寫(xiě)和運(yùn)行的。
單機(jī)(非分布式)模式
這種模式在一臺(tái)單機(jī)上運(yùn)行,沒(méi)有分布式文件系統(tǒng),而是直接讀寫(xiě)本地操作系統(tǒng)的文件系統(tǒng)。
代碼清單1
- $ cd /cygdrive/c/hadoop-0.16.0
- $ mkdir test-in
- $ cd test-in
- #在 test-in 目錄下創(chuàng)建兩個(gè)文本文件, WordCount 程序?qū)⒔y(tǒng)計(jì)其中各個(gè)單詞出現(xiàn)次數(shù)
- $ echo "hello world bye world" >file1.txt
- $ echo "hello hadoop goodbye hadoop" >file2.txt
- $ cd ..
- $ bin/hadoop jar hadoop-0.16.0-examples.jar wordcount test-in test-out
- #執(zhí)行完畢,下面查看執(zhí)行結(jié)果:
- $ cd test-out
- $ cat part-00000
- bye 1
- goodbye 1
- hadoop 2
- hello 2
- world 2
$ cd /cygdrive/c/hadoop-0.16.0
$ mkdir test-in
$ cd test-in
#在 test-in 目錄下創(chuàng)建兩個(gè)文本文件, WordCount 程序?qū)⒔y(tǒng)計(jì)其中各個(gè)單詞出現(xiàn)次數(shù)
$ echo "hello world bye world" >file1.txt
$ echo "hello hadoop goodbye hadoop" >file2.txt
$ cd ..
$ bin/hadoop jar hadoop-0.16.0-examples.jar wordcount test-in test-out
#執(zhí)行完畢,下面查看執(zhí)行結(jié)果:
$ cd test-out
$ cat part-00000
bye 1
goodbye 1
hadoop 2
hello 2
world 2
注意事項(xiàng):運(yùn)行 bin/hadoop jar hadoop-0.16.0-examples.jar wordcount test-in
test-out 時(shí),務(wù)必注意第一個(gè)參數(shù)是 jar, 不是 -jar, 當(dāng)你用 -jar
時(shí),不會(huì)告訴你是參數(shù)錯(cuò)了,報(bào)告出來(lái)的錯(cuò)誤信息是:Exception in thread "main"
java.lang.NoClassDefFoundError: org/apache/hadoop/util/ProgramDriver,
筆者當(dāng)時(shí)以為是 classpath 的設(shè)置問(wèn)題,浪費(fèi)了不少時(shí)間。通過(guò)分析 bin/hadoop 腳本可知,-jar 并不是 bin/hadoop
腳本定義的參數(shù),此腳本會(huì)把 -jar 作為 Java 的參數(shù),Java 的-jar 參數(shù)表示執(zhí)行一個(gè) Jar 文件(這個(gè) Jar
文件必須是一個(gè)可執(zhí)行的 Jar,即在 MANIFEST 中定義了主類), 此時(shí)外部定義的 classpath 是不起作用的,因而會(huì)拋出
java.lang.NoClassDefFoundError 異常。而 jar 是 bin/hadoop 腳本定義的參數(shù),會(huì)調(diào)用 Hadoop
自己的一個(gè)工具類 RunJar,這個(gè)工具類也能夠執(zhí)行一個(gè) Jar 文件,并且外部定義的 classpath 有效。
偽分布式運(yùn)行模式
這種模式也是在一臺(tái)單機(jī)上運(yùn)行,但用不同的 Java 進(jìn)程模仿分布式運(yùn)行中的各類結(jié)點(diǎn) ( NameNode, DataNode,
JobTracker, TaskTracker, Secondary NameNode ),請(qǐng)注意分布式運(yùn)行中的這幾個(gè)結(jié)點(diǎn)的區(qū)別:
從分布式存儲(chǔ)的角度來(lái)說(shuō),集群中的結(jié)點(diǎn)由一個(gè) NameNode 和若干個(gè) DataNode 組成, 另有一個(gè) Secondary
NameNode 作為 NameNode 的備份。從分布式應(yīng)用的角度來(lái)說(shuō),集群中的結(jié)點(diǎn)由一個(gè) JobTracker 和若干個(gè)
TaskTracker 組成,JobTracker 負(fù)責(zé)任務(wù)的調(diào)度,TaskTracker 負(fù)責(zé)并行執(zhí)行任務(wù)。TaskTracker 必須運(yùn)行在
DataNode 上,這樣便于數(shù)據(jù)的本地計(jì)算。JobTracker 和 NameNode 則無(wú)須在同一臺(tái)機(jī)器上。
(1) 按代碼清單2修改 conf/hadoop-site.xml。注意 conf/hadoop-default.xml 中是
Hadoop 缺省的參數(shù),你可以通過(guò)讀此文件了解 Hadoop 中有哪些參數(shù)可供配置,但不要修改此文件。可通過(guò)修改
conf/hadoop-site.xml 改變?nèi)笔?shù)值,此文件中設(shè)置的參數(shù)值會(huì)覆蓋 conf/hadoop-default.xml
的同名參數(shù)。
代碼清單 2
- <configuration>
- <property>
- <name>fs.default.name</name>
- <value>localhost:9000</value>
- </property>
- <property>
- <name>mapred.job.tracker</name>
- <value>localhost:9001</value>
- </property>
- <property>
- <name>dfs.replication</name>
- <value>1</value>
- </property>
- </configuration>
<configuration>
<property>
<name>fs.default.name</name>
<value>localhost:9000</value>
</property>
<property>
<name>mapred.job.tracker</name>
<value>localhost:9001</value>
</property>
<property>
<name>dfs.replication</name>
<value>1</value>
</property>
</configuration>
參數(shù) fs.default.name 指定 NameNode 的 IP 地址和端口號(hào)。缺省值是 file:///, 表示使用本地文件系統(tǒng), 用于單機(jī)非分布式模式。此處我們指定使用運(yùn)行于本機(jī) localhost 上的 NameNode。
參數(shù) mapred.job.tracker 指定 JobTracker 的 IP 地址和端口號(hào)。缺省值是 local, 表示在本地同一
Java 進(jìn)程內(nèi)執(zhí)行 JobTracker 和 TaskTracker, 用于單機(jī)非分布式模式。此處我們指定使用運(yùn)行于本機(jī) localhost
上的 JobTracker ( 用一個(gè)單獨(dú)的 Java 進(jìn)程做 JobTracker )。
參數(shù) dfs.replication 指定 HDFS 中每個(gè) Block 被復(fù)制的次數(shù),起數(shù)據(jù)冗余備份的作用。在典型的生產(chǎn)系統(tǒng)中,這個(gè)數(shù)常常設(shè)置為3。
(2)配置 SSH,如代碼清單3所示:
代碼清單 3
- $ ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa
- $ cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys
$ ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa
$ cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys
配置完后,執(zhí)行一下 ssh localhost, 確認(rèn)你的機(jī)器可以用 SSH 連接,并且連接時(shí)不需要手工輸入密碼。
(3)格式化一個(gè)新的分布式文件系統(tǒng), 如代碼清單4所示:
代碼清單 4
- $ cd /cygdrive/c/hadoop-0.16.0
- $ bin/hadoop namenode –format
$ cd /cygdrive/c/hadoop-0.16.0
$ bin/hadoop namenode –format
(4) 啟動(dòng) hadoop 進(jìn)程, 如代碼清單5所示。控制臺(tái)上的輸出信息應(yīng)該顯示啟動(dòng)了 namenode, datanode,
secondary namenode, jobtracker, tasktracker。啟動(dòng)完成之后,通過(guò) ps –ef
應(yīng)該可以看到啟動(dòng)了5個(gè)新的 java 進(jìn)程。
代碼清單 5
- $ bin/start-all.sh
- $ ps –ef
$ bin/start-all.sh
$ ps –ef
(5) 運(yùn)行 wordcount 應(yīng)用, 如代碼清單6所示:
代碼清單 6
- $ bin/hadoop dfs -put ./test-in input
- #將本地文件系統(tǒng)上的 ./test-in 目錄拷到 HDFS 的根目錄上,目錄名改為 input
- #執(zhí)行 bin/hadoop dfs –help 可以學(xué)習(xí)各種 HDFS 命令的使用。
- $ bin/hadoop jar hadoop-0.16.0-examples.jar wordcount input output
- #查看執(zhí)行結(jié)果:
- #將文件從 HDFS 拷到本地文件系統(tǒng)中再查看:
- $ bin/hadoop dfs -get output output
- $ cat output/*
- #也可以直接查看
- $ bin/hadoop dfs -cat output/*
- $ bin/stop-all.sh #停止 hadoop 進(jìn)程
$ bin/hadoop dfs -put ./test-in input
#將本地文件系統(tǒng)上的 ./test-in 目錄拷到 HDFS 的根目錄上,目錄名改為 input
#執(zhí)行 bin/hadoop dfs –help 可以學(xué)習(xí)各種 HDFS 命令的使用。
$ bin/hadoop jar hadoop-0.16.0-examples.jar wordcount input output
#查看執(zhí)行結(jié)果:
#將文件從 HDFS 拷到本地文件系統(tǒng)中再查看:
$ bin/hadoop dfs -get output output
$ cat output/*
#也可以直接查看
$ bin/hadoop dfs -cat output/*
$ bin/stop-all.sh #停止 hadoop 進(jìn)程
故障診斷
(1) 執(zhí)行 $ bin/start-all.sh 啟動(dòng) Hadoop 進(jìn)程后,會(huì)啟動(dòng)5個(gè) java 進(jìn)程, 同時(shí)會(huì)在 /tmp
目錄下創(chuàng)建五個(gè) pid 文件記錄這些進(jìn)程 ID 號(hào)。通過(guò)這五個(gè)文件,可以得知 namenode, datanode, secondary
namenode, jobtracker, tasktracker 分別對(duì)應(yīng)于哪一個(gè) Java 進(jìn)程。當(dāng)你覺(jué)得 Hadoop
工作不正常時(shí),可以首先查看這5個(gè) java 進(jìn)程是否在正常運(yùn)行。
(2) 使用 web 接口。訪問(wèn) http://localhost:50030 可以查看 JobTracker 的運(yùn)行狀態(tài)。訪問(wèn)
http://localhost:50060 可以查看 TaskTracker 的運(yùn)行狀態(tài)。訪問(wèn) http://localhost:50070
可以查看 NameNode 以及整個(gè)分布式文件系統(tǒng)的狀態(tài),瀏覽分布式文件系統(tǒng)中的文件以及 log 等。
(3) 查看 ${HADOOP_HOME}/logs 目錄下的 log 文件,namenode, datanode, secondary
namenode, jobtracker, tasktracker 各有一個(gè)對(duì)應(yīng)的 log 文件,每一次運(yùn)行的計(jì)算任務(wù)也有對(duì)應(yīng)用 log
文件。分析這些 log 文件有助于找到故障原因。
結(jié)束語(yǔ)
現(xiàn)在,你已經(jīng)了解了 MapReduce 計(jì)算模型,分布式文件系統(tǒng) HDFS,分布式并行計(jì)算等的基本原理, 并且有了一個(gè)可以運(yùn)行的 Hadoop 環(huán)境,運(yùn)行了一個(gè)基于 Hadoop 的并行程序。
posted on 2010-08-06 09:42
何克勤 閱讀(341)
評(píng)論(0) 編輯 收藏 所屬分類:
數(shù)據(jù)庫(kù)和SQL 、
其他