[Hadoop] Hadoop學習歷程 [持續更新中…]


1. Hadoop FS Shell

  Hadoop之所以可以實現分布式計算,主要的原因之一是因為其背后的分布式文件系統(HDFS)。所以,對於Hadoop的文件操作需要有一套全新的shell指令來完成,而這就是Hadoop FS Shell。它主要是用於對Hadoop平台進行文件系統的管理。

  有關HDFS的介紹博客請移步:Hadoop學習筆記之Hadoop基礎

  有關Hadoop FS Shell的學習文檔:Hadoop FS Shell學習文檔

2. Hadoop Streaming

  我們知道Hadoop集群上的一些MapReduce代碼一般是利用Java來進行開發的,那么對於很多像博主一樣的不會Java的同學該怎么辦呢,是不是我們必須要在使用Hadoop之前要學會Java呢?當然,如果Java對你沒有什么幫助的話,你是完全沒有必要額外為了Hadoop來學習Java的。Hadoop Streaming就是Hadoop為了幫助用戶創建和運行一些特殊的map/reduce作業而開發的一個工具,它可以被看做是一個API,可以使用戶很方便地利用一些腳本語言(比如,bash shell或者Python)來寫Mapper和Reducer。

  下面是Hadoop Streaming的學習文檔:Hadoop Streaming學習文檔

3. Hadoop的輸入和輸出

  Hadoop的輸入和輸出分別為標准輸入和標准輸出,這是在學習hadoop時首先要記住的。對於第一次編寫hadoop job的同學來說,如果沒有認識到這點的重要性的話,可能都不知道hadoop如何在本地進行測試。Hadoop的輸入輸出是基於標准輸入和標准輸出的,那么我們在本地測試的時候就要利用bash命令來模擬這個過程,所以常見的unittest形式如下:

cat input | mapper | sort | reducer > output

  其中的sort命令的左右是在模擬reducer輸入的過程。對於數據流而言,具有相同key的數據流會聚合在一起(但是value是無序的),而且會被分發給同一個reducer,所以sort命令主要是在模擬這個過程,關於這個問題在下邊的combiner和partitioner部分會進行詳細介紹。

4. Hadoop MapReduce & Shuffler

  我們學習Hadoop實際上就是在學習一種全新的計算框架,它基於分布式的技術存儲,利用MapReduce思想實現海量數據處理的目的。在沒有實際接觸Hadoop時,很多參考書上都這樣說:MapReduce主要為兩個階段:Map階段和Reduce階段。這句話確實沒有錯,但是如果想完全的理解整個MapReduce思想,除了認識上述兩個階段還要深刻理解一個很重要的中間過程——shuffler,其中shuffler包含了combiner和partitioner。

  下圖為MapReduce的整體框架,其中shuffler部分的操作介於Mapper和Reducer之間,它的主要功能為處理Mapper的輸出並為Reducer提供相應的輸入文件,主要操作為combiner和partitioner。

13503D3B515Z-YM64

  我們可以這樣來理解上述的三種中間操作:

  combiner:分為Mapper端和Reducer端,主要作用是將鍵值對中具有相同key的放在一起;

  partitioner:把鍵值對按照key分配給reducer。

  combiner和partitioner兩者結合可以使得每一個Reducer的輸入是按照key進行聚合的,而且同一個key所對應的數據流只會被分配到同一個Reducer,這就極大地簡化了Reducer的任務。

  下圖為顯示了combiner和partitioner兩個中間操作的MapReduce框架圖,這個例子是做詞頻統計:

140930105035081 

  我們可以看到combiner的作用就是按照key將Mapper的輸出進行聚合,而partitioner會將所有combiner的結果按照key進行分發,分發給不同的Reducer進行數據的處理。我們在Reducer端可以看到兩點:

  第一,所有具有相同key的數據流均被分發到同一個Reducer;

  第二,每個Reducer的輸入中數據流是按照key進行聚合的,即具有相同key的數據流是連在一起的。

這樣我們在Reducer端就可以很輕松的完成詞頻統計的任務,我們可以按照數據流的順序進行詞頻的統計,如果當前數據流的key與上一個數據流的key相同,那么就將該key對應的詞頻進行累加,如果不同說明該key已經被統計完成,則進行下一個詞的統計即可。

  此外,在hadoop的配置中我們可以為partitioner配置相應的參數來控制partitioner按照不同的列來進行數據的切分,hadoop的默認設置是按照key進行數據的切分。

  其實除了combiner和partitioner以外,還有一些中間操作也需要進行深刻的理解,比如hadoop的sort過程。在這里,我們可以簡單了解一下Reducer端的sort,它其實是一種二次排序(secondary sort)。我們知道在hadoop中每個Reducer的輸入數據流中,數據流都是按照key聚合好的,但是其對應value則是無序的,即同一個job運行多次,由於Mapper完成的順序不同,Reducer收到的value的順序則是不固定的,那么如何才能使得Reducer接收的value成為有序的呢?這就是secondary sort需要解決的問題,它的應用場景常見的有求每個key下的最小/最大value值等。

  此外,我們也可以通過參數來控制secondary sort相應的作用域。

5. Hadoop常見操作

5.1 count操作

  count(計數/統計)是hadoop最為常見的操作之一。它的基本思想是就是上述詞頻統計的例子所講述的,由於每個Reducer的輸入都是按照key進行聚合的,所以可以根據key來順序的進行累加。

5.2 join操作

  join(拼接)是hadoop中最為常見的操作之一,它的主要任務就是將多張數據表按照某個字段拼接成一個表。要想寫出join操作需要考慮周全,否則會得到意想不到的結果。(PS:我在剛開始run第一個join job的時候,發現輸出結果總是不對,檢查了mapper和reducer的代碼邏輯覺得都沒有問題,一直不知道是哪里出問題,最后終於找到了原因,原來是MapReduce參數設置的問題: Mapper的output key fields = 2(按第1,2列排序);Reducer partition fields = 1(按第一列切分給reducer作為輸入)。)

  join的思想有很多種,但是常用的一種可以這樣來理解:

  mapper階段:由於數據流來自不同的數據表,所以mapper是將每一個數據流進行打標簽(tag),用於區別不同表的數據流;

  reducer階段:根據mapper中的tag來區分數據流,並對於不同的數據流按照自己的業務需求設計不同的操作,最后將不同的表進行拼接。

  上述的join思想被稱為是reducer端拼接。

  join操作還有一個巧妙的應用就是加載大詞典,避免直接利用streaming加載一些特別大的詞典。比如,我們現在要處理海量的日志,命中詞典中userid的日志挑選出來,問題很簡單,但是詞表很大,可能內存不足以加載,這時候怎么辦?我們借助join的思想:將大詞典看作是一份特殊的日志,將兩份日志join后輸出即可滿足要求了。[20160519 update.]

5.3 其他操作

  除了上述的count和join兩種常用的操作,hadoop還有很多操作,比如簡單的字段處理操作。在簡單的字段處理操作中,比如加/減某個字段,改寫某個字段,抽取某些字段等等,我們只需要mapper就可以了,此時不需要reducer進行任何操作,這時候reducer直接輸出mapper的結果就可以了,在streaming中reducer端實際上為一個cat命令。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM