Hadoop技術原理總結

Hadoop技術原理總結java

一、Hadoop運行原理
Hadoop是一個開源的可運行於大規模集羣上的分佈式並行編程框架,其最核心的設計包括:MapReduce和HDFS。基於 Hadoop,你能夠輕鬆地編寫可處理海量數據的分佈式並行程序,並將其運行於由成百上千個結點組成的大規模計算機集羣上。
基於MapReduce計算模型編寫分佈式並行程序相對簡單,程序員的主要工做就是設計實現Map和Reduce類,其它的並行編程中的種種複雜問題,如分佈式存儲,工做調度,負載平衡,容錯處理,網絡通訊等,均由 MapReduce框架和HDFS文件系統負責處理,程序員徹底不用操心。換句話說程序員只須要關心本身的業務邏輯便可,沒必要關心底層的通訊機制等問題,便可編寫出複雜高效的並行程序。若是說分佈式並行編程的難度足以讓普通程序員望而生畏的話,開源的 Hadoop的出現極大的下降了它的門檻。
二、Mapreduce原理
簡單的說:MapReduce框架的核心步驟主要分兩部分:Map和Reduce。當你向MapReduce框架提交一個計算做業時,它會首先把計算做業拆分紅若干個Map任務,而後分配到不一樣的節點上去執行,每個Map任務處理輸入數據中的一部分,當Map任務完成後,它會生成一些中間文件,這些中間文件將會做爲Reduce任務的輸入數據。Reduce對數據作進一步處理以後,輸出最終結果。
MapReduce是Hadoop的核心技術之一,爲分佈式計算的程序設計提供了良好的編程接口,而且屏蔽了底層通訊原理,使得程序員只需關心業務邏輯本事,就可輕易的編寫出基於集羣的分佈式並行程序。從它名字上來看,大體能夠看出個兩個動詞Map和Reduce,「Map(展開)」就是將一個任務分解成爲多個子任務並行的執行,「Reduce」就是將分解後多任務處理的結果彙總起來,得出最後的分析結果並輸出。
適合用 MapReduce來處理的數據集(或任務)有一個基本要求:待處理的數據集能夠分解成許多小的數據集,並且每個小數據集均可以徹底並行地進行處理。
Map-Reduce的處理過程主要涉及如下四個部分:
Client進程:用於提交Map-reduce任務job;
JobTracker進程:其爲一個Java進程,其main class爲JobTracker;
TaskTracker進程:其爲一個Java進程,其main class爲TaskTracker;
HDFS:Hadoop分佈式文件系統,用於在各個進程間共享Job相關的文件;
其中JobTracker進程做爲主控,用於調度和管理其它的TaskTracker進程, JobTracker能夠運行於集羣中任一臺計算機上,一般狀況下配置JobTracker進程運行在NameNode節點之上。TaskTracker負責執行JobTracker進程分配給的任務,其必須運行於 DataNode 上,即 DataNode 既是數據存儲結點,也是計算結點。 JobTracker將Map任務和Reduce任務分發給空閒的TaskTracker,讓這些任務並行運行,並負責監控任務的運行狀況。若是某一個 TaskTracker出故障了,JobTracker會將其負責的任務轉交給另外一個空閒的TaskTracker從新運行。
本地計算-原理
數據存儲在哪一臺計算機上,就由這臺計算機進行這部分數據的計算,這樣能夠減小數據在網絡上的傳輸,下降對網絡帶寬的需求。在Hadoop這樣的基於集羣的分佈式並行系統中,計算結點能夠很方便地擴充,而因它所可以提供的計算能力近乎是無限的,可是由是數據須要在不一樣的計算機之間流動,故網絡帶寬變成了瓶頸,是很是寶貴的,「本地計算」是最有效的一種節約網絡帶寬的手段,業界把這形容爲「移動計算比移動數據更經濟」。
三、HDFS存儲的機制
Hadoop的分佈式文件系統 HDFS是創建在Linux文件系統之上的一個虛擬分佈式文件系統,它由一個管理節點 ( NameNode )和N個數據節點 ( DataNode )組成,每一個節點均是一臺普通的計算機。在使用上同咱們熟悉的單機上的文件系統很是相似,同樣能夠建目錄,建立,複製,刪除文件,查看文件內容等。但其底層實現上是把文件切割成Block(塊),而後這些 Block分散地存儲於不一樣的 DataNode 上,每一個 Block還能夠複製數份存儲於不一樣的 DataNode上,達到容錯容災之目的。NameNode則是整個 HDFS的核心,它經過維護一些數據結構,記錄了每個文件被切割成了多少個 Block,這些 Block能夠從哪些 DataNode中得到,各個 DataNode的狀態等重要信息。
HDFS的數據塊
每一個磁盤都有默認的數據塊大小,這是磁盤進行讀寫的基本單位.構建於單個磁盤之上的文件系統經過磁盤塊來管理該文件系統中的塊.該文件系統中的塊通常爲磁盤塊的整數倍.磁盤塊通常爲512字節.HDFS也有塊的概念,默認爲64MB(一個map處理的數據大小).HDFS上的文件也被劃分爲塊大小的多個分塊,與其餘文件系統不一樣的是,HDFS中小於一個塊大小的文件不會佔據整個塊的空間.
任務粒度——數據切片(Splits)
把原始大數據集切割成小數據集時,一般讓小數據集小於或等於 HDFS中一個 Block的大小(缺省是 64M),這樣可以保證一個小數據集位於一臺計算機上,便於本地計算。有 M個小數據集待處理,就啓動 M個 Map任務,注意這 M個 Map任務分佈於 N臺計算機上並行運行,Reduce任務的數量 R則可由用戶指定。
HDFS用塊存儲帶來的第一個明顯的好處一個文件的大小能夠大於網絡中任意一個磁盤的容量,數據塊能夠利用磁盤中任意一個磁盤進行存儲.第二個簡化了系統的設計,將控制單元設置爲塊,可簡化存儲管理,計算單個磁盤能存儲多少塊就相對容易.同時也消除了對元數據的顧慮,如權限信息,能夠由其餘系統單獨管理。
四、舉一個簡單的例子說明MapReduce的運行機制
以計算一個文本文件中每一個單詞出現的次數的程序爲例,<k1,v1>能夠是 <行在文件中的偏移位置,文件中的一行>,經 Map函數映射以後,造成一批中間結果 <單詞,出現次數>,而 Reduce函數則能夠對中間結果進行處理,將相同單詞的出現次數進行累加,獲得每一個單詞的總的出現次數。程序員

5.MapReduce的核心過程----Shuffle['fl]和Sort
shuffle是mapreduce的心臟,瞭解了這個過程,有助於編寫效率更高的mapreduce程序和hadoop調優。
Shuffle是指從Map產生輸出開始,包括系統執行排序以及傳送Map輸出到Reducer做爲輸入的過程。以下圖所示:編程

首先從Map端開始分析,當Map開始產生輸出的時候,他並非簡單的把數據寫到磁盤,由於頻繁的操做會致使性能嚴重降低,他的處理更加複雜,數據首先是寫到內存中的一個緩衝區,並做一些預排序,以提高效率,如圖:

   每一個Map任務都有一個用來寫入「輸出數據」的「循環內存緩衝區」,這個緩衝區默認大小是100M(能夠經過io.sort.mb屬性來設置具體的大小),當緩衝區中的數據量達到一個特定的閥值(io.sort.mb * io.sort.spill.percent,其中io.sort.spill.percent默認是0.80)時,系統將會啓動一個後臺線程把緩衝區中的內容spill到磁盤。在spill過程當中,Map的輸出將會繼續寫入到緩衝區,但若是緩衝區已經滿了,Map就會被阻塞直到spill完成。spill線程在把緩衝區的數據寫到磁盤前,會對他進行一個二次排序,首先根據數據所屬的partition排序,而後每一個partition中再按Key排序。輸出包括一個索引文件和數據文件,若是設定了Combiner,將在排序輸出的基礎上進行。Combiner就是一個Mini Reducer,它在執行Map任務的節點自己運行,先對Map的輸出做一次簡單的Reduce,使得Map的輸出更緊湊,更少的數據會被寫入磁盤和傳送到Reducer。Spill文件保存在由mapred.local.dir指定的目錄中,Map任務結束後刪除。
   每當內存中的數據達到spill閥值的時候,都會產生一個新的spill文件,因此在Map任務寫完他的最後一個輸出記錄的時候,可能會有多個spill文件,在Map任務完成前,全部的spill文件將會被歸併排序爲一個索引文件和數據文件。如圖3所示。這是一個多路歸併過程,最大歸併路數由io.sort.factor控制(默認是10)。若是設定了Combiner,而且spill文件的數量至少是3(由min.num.spills.for.combine屬性控制),那麼Combiner將在輸出文件被寫入磁盤前運行以壓縮數據。

  對寫入到磁盤的數據進行壓縮(這種壓縮同Combiner的壓縮不同)一般是一個很好的方法,由於這樣作使得數據寫入磁盤的速度更快,節省磁盤空間,並減小須要傳送到Reducer的數據量。默認輸出是不被壓縮的,但能夠很簡單的設置mapred.compress.map.output爲true啓用該功能。壓縮所使用的庫由mapred.map.output.compression.codec來設定。
  當spill 文件歸併完畢後,Map 將刪除全部的臨時spill文件,並告知TaskTracker任務已完成。Reducers經過HTTP來獲取對應的數據。用來傳輸partitions數據的工做線程個數由tasktracker.http.threads控制,這個設定是針對每個TaskTracker的,並非單個Map,默認值爲40,在運行大做業的大集羣上能夠增大以提高數據傳輸速率。
  如今讓咱們轉到Shuffle的Reduce部分。Map的輸出文件放置在運行Map任務的TaskTracker的本地磁盤上(注意:Map輸出老是寫到本地磁盤,可是Reduce輸出不是,通常是寫到HDFS),它是運行Reduce任務的TaskTracker所須要的輸入數據。Reduce任務的輸入數據分佈在集羣內的多個Map任務的輸出中,Map任務可能會在不一樣的時間內完成,只要有其中一個Map任務完成,Reduce任務就開始拷貝他的輸出。這個階段稱爲拷貝階段,Reduce任務擁有多個拷貝線程,能夠並行的獲取Map輸出。能夠經過設定mapred.reduce.parallel.copies來改變線程數。
  Reduce是怎麼知道從哪些TaskTrackers中獲取Map的輸出呢?當Map任務完成以後,會通知他們的父TaskTracker,告知狀態更新,而後TaskTracker再轉告JobTracker,這些通知信息是經過心跳通訊機制傳輸的,所以針對以一個特定的做業,jobtracker知道Map輸出與tasktrackers的映射關係。Reducer中有一個線程會間歇的向JobTracker詢問Map輸出的地址,直到把全部的數據都取到。在Reducer取走了Map輸出以後,TaskTracker不會當即刪除這些數據,由於Reducer可能會失敗,他們會在整個做業完成以後,JobTracker告知他們要刪除的時候纔去刪除。
  若是Map輸出足夠小,他們會被拷貝到Reduce TaskTracker的內存中(緩衝區的大小由mapred.job.shuffle.input.buffer.percnet控制),或者達到了Map輸出的閥值的大小(由mapred.inmem.merge.threshold控制),緩衝區中的數據將會被歸併而後spill到磁盤。
   拷貝來的數據疊加在磁盤上,有一個後臺線程會將它們歸併爲更大的排序文件,這樣作節省了後期歸併的時間。對於通過壓縮的Map輸出,系統會自動把它們解壓到內存方便對其執行歸併。
   當全部的Map 輸出都被拷貝後,Reduce 任務進入排序階段(更恰當的說應該是歸併階段,由於排序在Map端就已經完成),這個階段會對全部的Map輸出進行歸併排序,這個工做會重複屢次才能完成。
   假設這裏有50 個Map 輸出(可能有保存在內存中的),而且歸併因子是10(由io.sort.factor控制,就像Map端的merge同樣),那最終須要5次歸併。每次歸併會把10個文件歸併爲一個,最終生成5箇中間文件。在這一步以後,系統再也不把5箇中間文件歸併成一個,而是排序後直接「喂」給Reduce函數,省去向磁盤寫數據這一步。最終歸併的數據能夠是混合數據,既有內存上的也有磁盤上的。因爲歸併的目的是歸併最少的文件數目,使得在最後一次歸併時總文件個數達到歸併因子的數目,因此每次操做所涉及的文件個數在實際中會更微妙些。譬如,若是有40個文件,並非每次都歸併10個最終獲得4個文件,相反第一次只歸併4個文件,而後再實現三次歸併,每次10個,最終獲得4個歸併好的文件和6個未歸併的文件。要注意,這種作法並無改變歸併的次數,只是最小化寫入磁盤的數據優化措施,由於最後一次歸併的數據老是直接送到Reduce函數那裏。在Reduce階段,Reduce函數會做用在排序輸出的每個key上。這個階段的輸出被直接寫到輸出文件系統,通常是HDFS。在HDFS中,由於TaskTracker節點也運行着一個DataNode進程,因此第一個塊備份會直接寫到本地磁盤。到此,MapReduce的Shuffle和Sort分析完畢。

六、Hadoop中Combiner的做用
6.1 Partition
把 Map任務輸出的中間結果按 key的範圍劃分紅 R份( R是預先定義的 Reduce任務的個數),劃分時一般使用hash函數如: hash(key) mod R,這樣能夠保證某一段範圍內的key,必定是將會由一個Reduce任務來處理,這樣能夠簡化 Reduce獲取計算數據的過程。
6.2 Combine操做
在 partition以前,還能夠對中間結果先作 combine,即將中間結果中有相同 key的 <key, value>對合併成一對。combine的過程與 Reduce的過程相似,不少狀況下就能夠直接使用 Reduce函數,但 combine是做爲 Map任務的一部分,在執行完 Map函數後緊接着執行的,而Reduce必須在全部的Map操做完成後才能進行。Combine可以減小中間結果中 <key, value>對的數目,從而減小網絡流量。
6.3 Reduce任務從 Map任務結點取中間結果
Map 任務的中間結果在作完 Combine和 Partition以後,以文件形式存於本地磁盤。中間結果文件的位置會通知主控 JobTracker,JobTracker再通知 Reduce任務到哪個DataNode上去取中間結果。注意全部的 Map任務產生中間結果均按其 Key用同一個 Hash函數劃分紅了 R份,R個 Reduce任務各自負責一段 Key區間。每一個 Reduce須要向許多個原Map任務結點以取得落在其負責的Key區間內的中間結果,而後執行 Reduce函數,造成一個最終的結果文件。
6.4 任務管道
有R個 Reduce任務,就會有 R個最終結果,不少狀況下這 R個最終結果並不須要合併成一個最終結果。由於這 R個最終結果又能夠作爲另外一個計算任務的輸入,開始另外一個並行計算任務。服務器

這個 MapReduce的計算過程簡而言之,就是將大數據集分解爲成百上千的小數據集,每一個(或若干個)數據集分別由集羣中的一個結點(通常就是一臺普通的計算機)進行處理並生成中間結果,而後這些中間結果又由大量的結點進行合併,造成最終結果。

計算模型的核心是 Map 和 Reduce 兩個函數,這兩個函數由用戶負責實現,功能是按必定的映射規則將輸入的 <key, value>對轉換成另外一個或一批 <key, value>對輸出。
6.五、總結
(1)、combiner使用的合適,能夠在知足業務的狀況下提高job的速度,若是不合適,則將致使輸出的結果不正確,可是不是全部的場合都適合combiner。根據本身的業務來使用。hadoop就是map和 reduce的過程。服務器上一個目錄節點+多個數據節點。將程序傳送到各個節點,在數據節點上進行計算
(2)、將數據存儲到不一樣節點,用map方式對應管理,在各個節點進行計算,採用reduce進行合併結果集
(3)、就是經過java程序和目錄節點配合,將數據存放到不一樣數據節點上
(4)、看上邊的2.注意,分佈式注重的是計算,不是每一個場景都適合
(5)、將文件存放到不一樣的數據節點,而後每一個節點計算出前十個進行reduce的計算。網絡

相關文章
相關標籤/搜索