hadoop的運行原理
hadoop主要由三方面組成:
1、HDFS
2、MapReduce
3、Hbase
Hadoop框架中最核心的設計就是:MapReduce和HDFS。MapReduce的思想是由Google的一篇論文所提及而被廣為流傳的, 簡單的一句話解釋MapReduce就是“任務的分解與結果的匯總”。HDFS是Hadoop分布式文件系統(Hadoop Distributed File System)的縮寫 ,為分布式計算存儲提供了底層支持。
MapReduce從它名字上來看就大致可以看出個緣由,兩個動詞Map和Reduce,“Map(展開)”就是將一個任務分解成為多個任 務,“Reduce”就是將分解后多任務處理的結果匯總起來,得出最后的分析結果。這不是什么新思想,其實在前面提到的多線程,多任務的設計就可以找到這 種思想的影子。不論是現實社會,還是在程序設計中,一項工作往往可以被拆分成為多個任務,任務之間的關系可以分為兩種:一種是不相關的任務,可以并行執 行;另一種是任務之間有相互的依賴,先后順序不能夠顛倒,這類任務是無法并行處理的。回到大學時期,教授上課時讓大家去分析關鍵路徑,無非就是找最省時的 任務分解執行方式。在分布式系統中,機器集群就可以看作硬件資源池,將并行的任務拆分,然后交由每一個空閑機器資源去處理,能夠極大地提高計算效率,同時 這種資源無關性,對于計算集群的擴展無疑提供了最好的設計保證。(其實我一直認為Hadoop的卡通圖標不應該是一個小象,應該是螞蟻,分布式計算就好比 螞蟻吃大象,廉價的機器群可以匹敵任何高性能的計算機,縱向擴展的曲線始終敵不過橫向擴展的斜線)。任務分解處理以后,那就需要將處理以后的結果再匯總起 來,這就是Reduce要做的工作。
下面這個圖很經典:
上圖中展現了整個HDFS三個重要角色:NameNode、DataNode和 Client。NameNode可以看作是分布式文件系統中的管理者,主要負責管理文件系統的命名空間、集群配置信息和存儲塊的復制等。NameNode 會將文件系統的Meta-data存儲在內存中,這些信息主要包括了文件信息、每一個文件對應的文件塊的信息和每一個文件塊在DataNode的信息等。 DataNode是文件存儲的基本單元,它將Block存儲在本地文件系統中,保存了Block的Meta-data,同時周期性地將所有存在的 Block信息發送給NameNode。Client就是需要獲取分布式文件系統文件的應用程序。這里通過三個操作來說明他們之間的交互關系。
文件寫入:
a):Client向NameNode發起文件寫入的請求。
b):NameNode根據文件大小和文件塊配置情況,返回給Client它所管理部分DataNode的信息。
c):Client將文件劃分為多個Block,根據DataNode的地址信息,按順序寫入到每一個DataNode塊中。
文件讀取:
a):Client向NameNode發起文件讀取的請求。
b):NameNode返回文件存儲的DataNode的信息。
c):Client讀取文件信息。
文件Block復制:
a):NameNode發現部分文件的Block不符合最小復制數或者部分DataNode失效。
b):通知DataNode相互復制Block。
c):DataNode開始直接相互復制.
下面綜合MapReduce和HDFS來看Hadoop的結構:
Hadoop結構示意圖
在Hadoop的系統中,會有一臺Master,主要負責NameNode的工作以及JobTracker的工作。JobTracker的主要職責 就是啟動、跟蹤和調度各個Slave的任務執行。還會有多臺Slave,每一臺Slave通常具有DataNode的功能并負責TaskTracker的 工作。TaskTracker根據應用要求來結合本地數據執行Map任務以及Reduce任務。
把自己平時工作當中的代碼貼出來解釋下可能會更好的理解:
FileInputFormat.setInputPaths(tempJob, hdfsHome); // 把本地的文件讀入到HDFS中
LOG.info(tempJobName + " data start .....");
tempJob.setJarByClass(tempMain.class); //設置這個Job運行是那個類
tempJob.setMapperClass(MultithreadedMapper.class); //設置這個job運行的map,這里面使用了本身map自帶的多線程實 現機制,這一點很重要,可以幫助我們提高運行的效率。
MultithreadedMapper.setMapperClass(tempJob,tempMapper.class); //設置這個job運行的map
MultithreadedMapper.setNumberOfThreads(tempJob, Integer.parseInt(tempThread));//設置多線程運行幾個線程
tempJob.setMapOutputKeyClass(LongWritable.class);// 設置map所輸出的key
tempJob.setMapOutputValueClass(StringArrayWritable.class); // 設置map所輸出的value
...... //下面還有reduce的一些,我這里的業務沒有涉及到,這里就不列出來了。
long start = System.currentTimeMillis();
boolean result = tempJob.waitForCompletion(true); //啟動一個job運行
long end = System.currentTimeMillis();