1. 程式人生 > >HAdoop基本原理1

HAdoop基本原理1

轉載記不清原著是哪裡了

Hadoop簡介Hadoop就是一個實現了Google雲端計算系統的開源系統,包括平行計算模型Map/Reduce,分散式檔案系統HDFS,以及分散式資料庫Hbase,同時Hadoop的相關專案也很豐富,包括ZooKeeper,Pig,Chukwa,Hive,Hbase,Mahout,flume等.這裡詳細分解這裡面的概念讓大家通過這篇文章瞭解到底是什麼hadoop:1.什麼是Map/Reduce,看下面的各種解釋:(1)MapReduce是hadoop的核心元件之一,hadoop要分散式包括兩部分,一是分散式檔案系統hdfs,一部是分散式計算框,就是mapreduce,缺一不可,也就是說,可以通過mapreduce很容易在hadoop平臺上進行分散式的計算程式設計。

(2)Mapreduce是一種程式設計模型,是一種程式設計方法,抽象理論。(3)下面是一個關於一個程式設計師是如何個妻子講解什麼是MapReduce?文章很長請耐心的看。我問妻子:“你真的想要弄懂什麼是MapReduce?” 她很堅定的回答說“是的”。 因此我問道:我: 你是如何準備洋蔥辣椒醬的?(以下並非準確食譜,請勿在家嘗試)妻子: 我會取一個洋蔥,把它切碎,然後拌入鹽和水,最後放進混合研磨機裡研磨。這樣就能得到洋蔥辣椒醬了。妻子: 但這和MapReduce有什麼關係?我: 你等一下。讓我來編一個完整的情節,這樣你肯定可以在15分鐘內弄懂MapReduce.妻子: 好吧。我:現在,假設你想用薄荷、洋蔥、番茄、辣椒、大蒜弄一瓶混合辣椒醬。你會怎麼做呢?
妻子: 我會取薄荷葉一撮,洋蔥一個,番茄一個,辣椒一根,大蒜一根,切碎後加入適量的鹽和水,再放入混合研磨機裡研磨,這樣你就可以得到一瓶混合辣椒醬了。我: 沒錯,讓我們把MapReduce的概念應用到食譜上。Map和Reduce其實是兩種操作,我來給你詳細講解下。Map(對映): 把洋蔥、番茄、辣椒和大蒜切碎,是各自作用在這些物體上的一個Map操作。所以你給Map一個洋蔥,Map就會把洋蔥切碎。 同樣的,你把辣椒,大蒜和番茄一一地拿給Map,你也會得到各種碎塊。 所以,當你在切像洋蔥這樣的蔬菜時,你執行就是一個Map操作。 Map操作適用於每一種蔬菜,它會相應地生產出一種或多種碎塊,在我們的例子中生產的是蔬菜塊。在Map操作中可能會出現有個洋蔥壞掉了的情況,你只要把壞洋蔥丟了就行了。所以,如果出現壞洋蔥了,Map操作就會過濾掉壞洋蔥而不會生產出任何的壞洋蔥塊。
Reduce(化簡):在這一階段,你將各種蔬菜碎都放入研磨機裡進行研磨,你就可以得到一瓶辣椒醬了。這意味要製成一瓶辣椒醬,你得研磨所有的原料。因此,研磨機通常將map操作的蔬菜碎聚集在了一起。妻子: 所以,這就是MapReduce?我: 你可以說是,也可以說不是。 其實這只是MapReduce的一部分,MapReduce的強大在於分散式計算。妻子: 分散式計算? 那是什麼?請給我解釋下吧。我: 沒問題。我: 假設你參加了一個辣椒醬比賽並且你的食譜贏得了最佳辣椒醬獎。得獎之後,辣椒醬食譜大受歡迎,於是你想要開始出售自制品牌的辣椒醬。假設你每天需要生產10000瓶辣椒醬,你會怎麼辦呢?妻子: 我會找一個能為我大量提供原料的供應商。我:是的..就是那樣的。那你能否獨自完成製作呢?也就是說,獨自將原料都切碎? 僅僅一部研磨機又是否能滿足需要?而且現在,我們還需要供應不同種類的辣椒醬,像洋蔥辣椒醬、青椒辣椒醬、番茄辣椒醬等等。妻子: 當然不能了,我會僱傭更多的工人來切蔬菜。我還需要更多的研磨機,這樣我就可以更快地生產辣椒醬了。我:沒錯,所以現在你就不得不分配工作了,你將需要幾個人一起切蔬菜。每個人都要處理滿滿一袋的蔬菜,而每一個人都相當於在執行一個簡單的Map操作。每一個人都將不斷的從袋子裡拿出蔬菜來,並且每次只對一種蔬菜進行處理,也就是將它們切碎,直到袋子空了為止。這樣,當所有的工人都切完以後,工作臺(每個人工作的地方)上就有了洋蔥塊、番茄塊、和蒜蓉等等。妻子:但是我怎麼會製造出不同種類的番茄醬呢?我:現在你會看到MapReduce遺漏的階段—攪拌階段。MapReduce將所有輸出的蔬菜碎都攪拌在了一起,這些蔬菜碎都是在以key為基礎的 map操作下產生的。攪拌將自動完成,你可以假設key是一種原料的名字,就像洋蔥一樣。 所以全部的洋蔥keys都會攪拌在一起,並轉移到研磨洋蔥的研磨器裡。這樣,你就能得到洋蔥辣椒醬了。同樣地,所有的番茄也會被轉移到標記著番茄的研磨器裡,並製造出番茄辣椒醬。4)上面都是從理論上來說明什麼是MapReduce,那麼咱們在MapReduce產生的過程和程式碼的角度來理解這個問題。如果想統計下過去10年計算機論文出現最多的幾個單詞,看看大家都在研究些什麼,那收集好論文後,該怎麼辦呢?  方法一:      我可以寫一個小程式,把所有論文按順序遍歷一遍,統計每一個遇到的單詞的出現次數,最後就可以知道哪幾個單詞最熱門了。 這種方法在資料集比較小時,是非常有效的,而且實現最簡單,用來解決這個問題很合適。  方法二:       寫一個多執行緒程式,併發遍歷論文。   這個問題理論上是可以高度併發的,因為統計一個檔案時不會影響統計另一個檔案。當我們的機器是多核或者多處理器,方法二肯定比方法一高效。但是寫一個多執行緒程式要比方法一困難多了,我們必須自己同步共享資料,比如要防止兩個執行緒重複統計檔案。 方法三:      把作業交給多個計算機去完成。   我們可以使用方法一的程式,部署到N臺機器上去,然後把論文集分成N份,一臺機器跑一個作業。這個方法跑得足夠快,但是部署起來很麻煩,我們要人工把程式copy到別的機器,要人工把論文集分開,最痛苦的是還要把N個執行結果進行整合(當然我們也可以再寫一個程式)。   方法四:      讓MapReduce來幫幫我們吧! MapReduce本質上就是方法三,但是如何拆分檔案集,如何copy程式,如何整合結果這些都是框架定義好的。我們只要定義好這個任務(使用者程式),其它都交給MapReduce。map函式和reduce函式  map函式和reduce函式是交給使用者實現的,這兩個函式定義了任務本身。 map函式:接受一個鍵值對(key-value pair),產生一組中間鍵值對。MapReduce框架會將map函式產生的中間鍵值對裡鍵相同的值傳遞給一個reduce函式。 reduce函式:接受一個鍵,以及相關的一組值,將這組值進行合併產生一組規模更小的值(通常只有一個或零個值)。   統計詞頻的MapReduce函式的核心程式碼非常簡短,主要就是實現這兩個函式。 map(String key, String value): // key: document name // value: document contents for each word w in value: EmitIntermediate(w, "1"); reduce(String key, Iterator values): // key: a word // values: a list of counts int result = 0; for each v in values: result += ParseInt(v); Emit(AsString(result));   在統計詞頻的例子裡,map函式接受的鍵是檔名,值是檔案的內容,map逐個遍歷單詞,每遇到一個單詞w,就產生一箇中間鍵值對<w, "1">,這表示單詞w咱又找到了一個;MapReduce將鍵相同(都是單詞w)的鍵值對傳給reduce函式,這樣reduce函式接受的鍵就是單詞w,值是一串"1"(最基本的實現是這樣,但可以優化),個數等於鍵為w的鍵值對的個數,然後將這些“1”累加就得到單詞w的出現次數。最後這些單詞的出現次數會被寫到使用者定義的位置,儲存在底層的分散式儲存系統(GFS或HDFS)。 工作原理上圖是論文裡給出的流程圖。一切都是從最上方的user program開始的,user program連結了MapReduce庫,實現了最基本的Map函式和Reduce函式。圖中執行的順序都用數字標記了。1.MapReduce庫先把user program的輸入檔案劃分為M份(M為使用者定義),每一份通常有16MB到64MB,如圖左方所示分成了split0~4;然後使用fork將使用者程序拷貝到叢集內其它機器上。 2.user program的副本中有一個稱為master,其餘稱為worker,master是負責排程的,為空閒worker分配作業(Map作業或者Reduce作業),worker的數量也是可以由使用者指定的。 3.被分配了Map作業的worker,開始讀取對應分片的輸入資料,Map作業數量是由M決定的,和split一一對應;Map作業從輸入資料中抽取出鍵值對,每一個鍵值對都作為引數傳遞給map函式,map函式產生的中間鍵值對被快取在記憶體中。 4.快取的中間鍵值對會被定期寫入本地磁碟,而且被分為R個區,R的大小是由使用者定義的,將來每個區會對應一個Reduce作業;這些中間鍵值對的位置會被通報給master,master負責將資訊轉發給Reduce worker。 5.master通知分配了Reduce作業的worker它負責的分割槽在什麼位置(肯定不止一個地方,每個Map作業產生的中間鍵值對都可能對映到所有R個不同分割槽),當Reduce worker把所有它負責的中間鍵值對都讀過來後,先對它們進行排序,使得相同鍵的鍵值對聚集在一起。因為不同的鍵可能會對映到同一個分割槽也就是同一個Reduce作業(誰讓分割槽少呢),所以排序是必須的。 6.reduce worker遍歷排序後的中間鍵值對,對於每個唯一的鍵,都將鍵與關聯的值傳遞給reduce函式,reduce函式產生的輸出會新增到這個分割槽的輸出檔案中。 6.當所有的Map和Reduce作業都完成了,master喚醒正版的user program,MapReduce函式呼叫返回user program的程式碼。   所有執行完畢後,MapReduce輸出放在了R個分割槽的輸出檔案中(分別對應一個Reduce作業)。使用者通常並不需要合併這R個檔案,而是將其作為輸入交給另一個MapReduce程式處理。整個過程中,輸入資料是來自底層分散式檔案系統(GFS)的,中間資料是放在本地檔案系統的,最終輸出資料是寫入底層分散式檔案系統(GFS)的。而且我們要注意Map/Reduce作業和map/reduce函式的區別:Map作業處理一個輸入資料的分片,可能需要呼叫多次map函式來處理每個輸入鍵值對;Reduce作業處理一個分割槽的中間鍵值對,期間要對每個不同的鍵呼叫一次reduce函式,Reduce作業最終也對應一個輸出檔案。總結:通過以上你是否瞭解什麼是MapReduce了那,什麼是key,怎麼過濾有效資料,怎麼得到自己想要的資料。MapReduce是一種程式設計思想,可以使用java來實現,C++來實現。Map的作用是過濾一些原始資料,Reduce則是處理這些資料,得到我們想要的結果,比如你想造出番茄辣椒醬。也就是我們使用hadoop,比方來進行日誌處理之後,得到我們想要的關心的資料