您好,登錄后才能下訂單哦!
Hadoop由兩部分組成,分別是分布式文件系統HDFS和分布式計算框架MapReduce。其中,分布式文件系統HDFS主要用于大規模數據的分布式存儲,而MapReduce則構建在分布式文件系統上,對于存儲在分布式文件系統的數據進行分布式計算。
HadoopMapReduce誕生于搜索領域,主要解決搜索引擎面臨的海量數據處理擴展性差的問題。它的實現很大程度上借鑒了Google MapReduce的設計思想,包括簡化編程接口、提高系統容錯性等。總結HadoopMapReduce設計目標,主要有以下幾個:
1、易于編程:傳統的分布式程序設計非常復雜,用戶需要關注的細節非常多,比如數據分片、數據傳輸、節點間通信等。因而設計分布式程序的門檻非常高。Hadoop的一個重要設計目標是簡化分布式程序設計,將所有并行程序均需要關注的設計細節抽象成公共模塊并交由系統實現,而用戶只需專注于自己的應用程序邏輯實現,這樣簡化了分布式程序設計且提高了開發效率。
2、良好的擴展性:隨著公司業務的發展,積累的數據量會越來越大,當數據量增加到一定程度后,現有的集群可能已經無法滿足其計算能力和存儲能力,這時候管理員可能期望通過添加機器以達到線性擴展集群能力的目的。
3、高容錯性:在分布式環境下。隨著集群規模的增加,集群中的故障率(這里的故障包括磁盤損壞、機器宕機、節點間通訊失敗等硬件故障和壞數據或者用戶程序bug產生的軟件故障)會顯著增加,進而導致任務失敗和數據丟失的可能性增加,為此,Hadoop通過計算遷移或者數據遷移等策略提高集群的可用性與容錯性。
MapReduce采用"分而治之"的思想,把對大規模數據集的操作,分發給一個主節點管理下的各個分節點共同完成,然后通過整合各個節點的中間結果,得到最終結果。簡單地說,MapReduce就是"任務的分解與結果的匯總"。
在Hadoop中,用于執行MapReduce任務的機器角色有兩個:一個是JobTracker;另一個是TaskTracker,JobTracker是用于調度工作的,TaskTracker是用于執行工作的。一個Hadoop集群中只有一臺JobTracker。
在分布式計算中,MapReduce框架負責處理了并行編程中分布式存儲、工作調度、負載均衡、容錯均衡、容錯處理以及網絡通信等復雜問題,把處理過程高度抽象為兩個函數:map和reduce,map負責把任務分解成多個任務,reduce負責把分解后多任務處理的結果匯總起來。
需要注意的是,用MapReduce來處理的數據集(或任務)必須具備這樣的特點:待處理的數據集可以分解成許多小的數據集,而且每一個小數據集都可以完全并行地進行處理。
同HDFS一樣,Hadoop MapReduce也采用了Master/Slaves(M/S)架構,如下圖所示,它主要由以下幾個組件組成:Client、JobTracker、TaskTracker和Task。
下面分別對這幾個組件進行介紹:
A、Client
用戶編寫的MapReduce程序通過Client提交到JobTracker端。同時。用戶可以通過Client提供的一些接口查看作業運行狀態。在Hadoop內部用“作業”(Job)表示MapReduce程序。一個MapReduce程序可以對應若干個作業,而每個作業被分解成若干個Map/Reduce任務(Task)。
B、JobTracker
JobTracker主要負責資源監控和作業調度。JobTracker監控所有TaskTracker與作業的健康狀況,一旦發現失敗情況后,其會將相應的任務轉移到其它節點。同時,JobTracker會跟蹤任務的執行進度、資源使用量等信息,并將這些信息告訴任務調度器,而調度器會在資源出現空閑時,選擇合適的任務使用這些資源。在Hadoop中,任務調度器是一個可插拔的模塊,用戶可以根據自己的需要設計相應的調度器。
C、TaskTracker
TaskTracker會周期性地通過Heartbeat將本節點上資源的使用情況和任務的運行進度匯報給JobTracker,同時接收JobTracker發送過來的命令并執行相應的操作(例如啟動新任務、殺死任務等)。
TaskTracker使用“slot”等量劃分本節點的數量,“slot”代表計算資源(CPU、內存等)。
一個Task獲取到一個slot后才有機會運行,而Hadoop調度器的作用就是將各個TaskTracker上的空閑slot分配給Task使用。
Slot分為Map slot和Reduce slot兩種,分別提供Map Task和Reduce Task。TaskTracker通過slot數目限定Task的并發度。
D、Task
Task分為Map Task和Reduce Task兩種,均有TaskTracker啟動。我們知道,HDFS以固定大小的block為基本單位存儲數據,而對于MapReduce而言,其處理基本單位是分片(split).
split是一個邏輯概念,它只包含一些元數據信息,比如數據起始位置、數據長度、數據所在節點等等。它的劃分方法完全由用戶自己決定,但是建議split的劃分大小與HDFS的block大小一致。
需要注意的是,split的多少決定Map Task的數目,因為每個split會交由一個Map Task處理。
Split與blcok的對應關系圖:
MapTask先將對應的split迭代解析成一個個key/value對,依次調用用戶自定義的map函數進行處理,最終將臨時結果存放到本地磁盤上,其中臨時數據被分成若干個partition,每個partition將被一個ReduceTask處理。
ReduceTask分為三個階段:第一步,從遠程節點上讀取Map Task中間結果,稱為Shuffle階段。第二步,按照key對key/value進行排序,稱為Sort階段。第三步,依次讀取<key,value list>,調用用戶自定義的reduce函數處理,并將最終結果存到HDFS上,稱為Reduce階段。
這段主要講解Map Reduce的物理實體作業的生命周期,即從作業提交到運行結束的整個過程。如下圖所示:
步驟 1 作業提交與初始化。用戶提交作業后,首先由 JobClient 實例將作業相關信息,比如將程序 jar 包、作業配置文件、分片元信息文件等上傳到分布式文件系統(一般為HDFS)上,其中,分片元信息文件記錄了每個輸入分片的邏輯位置信息。然后JobClient 通過 RPC通知JobTracker。JobTracker收到新作業提交請求后,由作業調度模塊對作業進 行初始化 :為作業創建一個JobInProgress對象以跟蹤作業運行狀況,而 JobInProgress 則會為每個Task創建一個TaskInProgress 對象以跟蹤每個任務的運行狀態,TaskInProgress 可能需要管理多個“Task 運行嘗試”(稱為“Task Attempt”)。
步驟 2 任務調度與監控。前面提到,任務調度和監控的功能均由JobTracker 完成。 TaskTracker 周期性地通過Heartbeat向JobTracker匯報本節點的資源使用情況,一旦出現空閑資源,JobTracker會按照一定的策略選擇一個合適的任務使用該空閑資源,這由任務調 度器完成。任務調度器是一個可插拔的獨立模塊,且為雙層架構,即首先選擇作業,然后從該作業中選擇任務,其中,選擇任務時需要重點考慮數據本地性。此外,JobTracker跟蹤作業的整個運行過程,并為作業的成功運行提供全方位的保障。首先,當TaskTracker或者Task失敗時,轉移計算任務 ;其次,當某個Task執行進度遠落后于同一作業的其他 Task 時, 為之啟動一個相同 Task,并選取計算快的Task結果作為最終結果。
步驟 3 任務運行環境準備。運行環境準備包括JVM啟動和資源隔離,均由TaskTracker 實現。TaskTracker為每個Task啟動一個獨立的JVM 以避免不同Task在運行過程中相互影響;同時,TaskTracker使用了操作系統進程實現資源隔離以防止Task濫用資源。
步驟 4 任務執行。TaskTracker 為 Task 準備好運行環境后,便會啟動Task。在運行過 程中,每個 Task 的最新進度首先由 Task 通過 RPC 匯報給TaskTracker,再由 TaskTracker 匯報給JobTracker。
步驟 5 作業完成。待所有 Task 執行完畢后,整個作業執行成功。
這些按照時間順序包括:輸入分片(input split)、map階段、combiner階段、shuffle階段和reduce階段。
1) 輸入分片(input split):在進行map計算之前,mapreduce會根據輸入文件計算輸入分片(input split),每個輸入分片(input split)針對一個map任務,輸入分片(input split)存儲的并非數據本身,而是一個分片長度和一個記錄數據的位置的數組,輸入分片(input split)往往和hdfs的block(塊)關系很密切,假如我們設定hdfs的塊的大小是64mb,如果我們輸入有三個文件,大小分別是3mb、65mb和127mb,那么mapreduce會把3mb文件分為一個輸入分片(input split),65mb則是兩個輸入分片(input split)而127mb也是兩個輸入分片(input split),換句話說我們如果在map計算前做輸入分片調整,例如合并小文件,那么就會有5個map任務將執行,而且每個map執行的數據大小不均,這個也是mapreduce優化計算的一個關鍵點。
2) map階段:就是程序員編寫好的map函數了,因此map函數效率相對好控制,而且一般map操作都是本地化操作也就是在數據存儲節點上進行;
3) combiner階段:combiner階段是程序員可以選擇的,combiner其實也是一種reduce操作,因此我們看見WordCount類里是用reduce進行加載的。Combiner是一個本地化的reduce操作,它是map運算的后續操作,主要是在map計算出中間文件前做一個簡單的合并重復key值的操作,例如我們對文件里的單詞頻率做統計,map計算時候如果碰到一個hadoop的單詞就會記錄為1,但是這篇文章里hadoop可能會出現n多次,那么map輸出文件冗余就會很多,因此在reduce計算前對相同的key做一個合并操作,那么文件會變小,這樣就提高了寬帶的傳輸效率,畢竟hadoop計算力寬帶資源往往是計算的瓶頸也是最為寶貴的資源,但是combiner操作是有風險的,使用它的原則是combiner的輸入不會影響到reduce計算的最終輸入,例如:如果計算只是求總數,最大值,最小值可以使用combiner,但是做平均值計算使用combiner的話,最終的reduce計算結果就會出錯。
4) shuffle階段:將map的輸出作為reduce的輸入的過程就是shuffle了,這個是mapreduce優化的重點地方。這里我不講怎么優化shuffle階段,講講shuffle階段的原理,因為大部分的書籍里都沒講清楚shuffle階段。Shuffle一開始就是map階段做輸出操作,一般mapreduce計算的都是海量數據,map輸出時候不可能把所有文件都放到內存操作,因此map寫入磁盤的過程十分的復雜,更何況map輸出時候要對結果進行排序,內存開銷是很大的,map在做輸出時候會在內存里開啟一個環形內存緩沖區,這個緩沖區專門用來輸出的,默認大小是100mb,并且在配置文件里為這個緩沖區設定了一個閥值,默認是0.80(這個大小和閥值都是可以在配置文件里進行配置的),同時map還會為輸出操作啟動一個守護線程,如果緩沖區的內存達到了閥值的80%時候,這個守護線程就會把內容寫到磁盤上,這個過程叫spill,另外的20%內存可以繼續寫入要寫進磁盤的數據,寫入磁盤和寫入內存操作是互不干擾的,如果緩存區被撐滿了,那么map就會阻塞寫入內存的操作,讓寫入磁盤操作完成后再繼續執行寫入內存操作,前面我講到寫入磁盤前會有個排序操作,這個是在寫入磁盤操作時候進行,不是在寫入內存時候進行的,如果我們定義了combiner函數,那么排序前還會執行combiner操作。每次spill操作也就是寫入磁盤操作時候就會寫一個溢出文件,也就是說在做map輸出有幾次spill就會產生多少個溢出文件,等map輸出全部做完后,map會合并這些輸出文件。這個過程里還會有一個Partitioner操作,對于這個操作很多人都很迷糊,其實Partitioner操作和map階段的輸入分片(Input split)很像,一個Partitioner對應一個reduce作業,如果我們mapreduce操作只有一個reduce操作,那么Partitioner就只有一個,如果我們有多個reduce操作,那么Partitioner對應的就會有多個,Partitioner因此就是reduce的輸入分片,這個程序員可以編程控制,主要是根據實際key和value的值,根據實際業務類型或者為了更好的reduce負載均衡要求進行,這是提高reduce效率的一個關鍵所在。到了reduce階段就是合并map輸出文件了,Partitioner會找到對應的map輸出文件,然后進行復制操作,復制操作時reduce會開啟幾個復制線程,這些線程默認個數是5個,程序員也可以在配置文件更改復制線程的個數,這個復制過程和map寫入磁盤過程類似,也有閥值和內存大小,閥值一樣可以在配置文件里配置,而內存大小是直接使用reduce的tasktracker的內存大小,復制時候reduce還會進行排序操作和合并文件操作,這些操作完了就會進行reduce計算了。
5) reduce階段:和map函數一樣也是程序員編寫的,最終結果是存儲在hdfs上的。
如圖所示:
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。