天天看點

《Hadoop與大資料挖掘》一2.4.2 MapReduce原理

本節書摘來華章計算機《hadoop與大資料挖掘》一書中的第2章 ,第2.4.2節,張良均 樊 哲 位文超 劉名軍 許國傑 周 龍 焦正升 著 更多章節内容可以通路雲栖社群“華章計算機”公衆号檢視。

1.通俗了解mapreduce原理

現在你接到一個任務,給你10本長篇英文小說,讓你統計這10本書中每一個單詞出現的次數。這便是hadoop程式設計中赫赫有名的helloworld程式:詞頻統計。這個任務的結果形式如表2-6所示。

《Hadoop與大資料挖掘》一2.4.2 MapReduce原理
《Hadoop與大資料挖掘》一2.4.2 MapReduce原理

即在這10本書中a共出現了12300次,ai共出現了63次……依次計算出每一個單詞出現多少次。天啊,這個工作必須由專業人士做呀,自己做的話還不累死呀。這時你可以把這個工作外包給一支職業分布式運算工程隊做。

分布式運算工程隊中按崗位有mapper、mapper助理comb-iner、mapper助理inputformat、mapper助理patitioner、運輸負責shuffle、reducer、reducer助理sort、reducer助理outputformat。除了combiner是非必需人員外,其他崗位都是必需的。下面描述一下這個工程隊是怎麼做這項工作的。

首先把這10本書分别分到10個mapper手中。mapper助理inputformat負責從書中讀取記錄,mapper負責記錄怎麼解析重新組織成新的格式。然後mapper把自己的處理結果排好序後放到書旁邊,等待shuffle取走結果。shuffle把取到的結果送給reducer助理sort,由sort負責把所有mapper的結果排好序,然後送給reducer來進行彙總,以得到最終的結果;最後,由reducer助理outputformat記錄到規定位置并存檔。

下面說明什麼時候需要combiner。maper助理inputforormat從書中一行行讀取記錄,給到mapper,mapper從inputformat的記錄中解析出一個個單詞,并進行記錄。mapper處理的結果形如“a出現了一次,a出現了一次,ai出現了一次……zhe出現了一次”。工作一段時間後發現負責搬運工作的suffle有點吃不消,這時就用到mapper助理combiner了。由combiner對的輸出結果進行短暫的彙總,把mapper的結果處理成形如“書本一中單詞a共出現1500次,ai出現了14次,are出現了80次……”這樣shuffle的壓力頓時減輕了許多。

對于每個崗位工程隊都是有預設時限的。但如果預設時限不能滿足需求,也可以對工作量進行自定義。

上面的過程描述了一個mapreduce工程隊是如何進行配合工作的。這個過程與mapreduce分布式運算是基本對應的。了解了上面的過程也就大概了解了hadoop的map-reduce過程了。

2. mapreduce過程解析

mapreduce過程可以解析為如下所示:

1)檔案在hdfs上被分塊存儲,datanode存儲實際的塊。

2)在map階段,針對每個檔案塊建立一個map任務,map任務直接運作在datanode上,即移動計算,而非資料,如圖2-30所示。

3)每個map任務處理自己的檔案塊,然後輸出新的鍵值對,如圖2-31所示。

4)map輸出的鍵值對經過shuffle/sort階段後,相同key的記錄會被輸送到同一個reducer中,同時鍵是排序的,值被放入一個清單中,如圖2-32所示。

5)每個reducer處理從map輸送過來的鍵值對,然後輸出新的鍵值對,一般輸出到hdfs上。

《Hadoop與大資料挖掘》一2.4.2 MapReduce原理

3.單詞計數源碼解析

上面的分析都是建立在理論基礎上的,這樣的分析有利于編寫mapreduce程式。但是如果要實際編寫一個mapreduce的簡單程式,還是不夠的,需要具體看示例代碼。這裡直接以官網提供的example代碼中的wordcount程式作為示例,進行代碼級别分析和說明。

首先,在hadoop的發行版中找到對應的代碼。在解壓下載下傳的hadoop2.6.0的發行版目錄中,找到hadoop-2.6.0sharehadoopmapreducesources目錄,該目錄下面有一個hadoop-mapreduce-examples-2.6.0-sources.jar檔案,使用壓縮檔案解壓縮該檔案,在目錄org/apache/hadoop/examples中即可找到wordcount.java檔案,如圖2-33所示。

《Hadoop與大資料挖掘》一2.4.2 MapReduce原理

找到該檔案後,使用文本軟體打開,或拷貝到eclipse工程中檢視,如代碼清單2-23所示。

下面對該代碼進行分析。

(1)應用程式driver分析

這裡的driver程式主要指的是main函數,在main函數裡面設定mapreduce程式的一些初始化設定,并送出任務等待程式運作完成,如代碼清單2-24所示。

下面,針對wordcount main函數代碼進行分析說明。

1)第1部分configuration代碼,初始化相關hadoop配置。在2.4.1節中也看到過,這裡直接建立一個執行個體即可。如果是在實際的應用程式中,可以通過conf.set()函數添加必要參數,即可直接運作。

2)第2部分代碼建立job,并設定主類。這裡的job執行個體需要把configuration的執行個體傳入,後面的“word count”是該mapreduce任務的任務名(注意這裡的方式使用的還是不推薦的mrv1的版本,推薦使用mrv2的版本)。

3)第3部分代碼設定mapper、reducer、combiner,這裡的設定代碼都是固定寫法,裡面的類名可以改變,一般情況下裡面的類名為實際任務mapper、reducer、combiner。

4)第4部分代碼設定輸出鍵值對格式。在mapreduce任務中涉及三個鍵值對格式:mapper輸入鍵值對格式,mapper輸出鍵值對格式,reducer輸入鍵值對格式,reducer輸出鍵值對格式。當mapper輸出鍵值對格式和reducer輸出鍵值對格式一樣的時候,可以隻設定輸出鍵值對的格式(這個其實就是reducer輸出的鍵值對格式),否則需要設定“job.setmapoutputkeyclass(text.class); job.setmapoutputkeyclass(intwritable.class);”。

5)第5、第6部分代碼設定輸入、輸出路徑,其實還有輸入、輸出檔案格式的設定,隻是這裡沒有設定,如果不是預設格式,那麼還是需要設定的。

6)最後部分代碼是送出mapreduce任務運作(是固定寫法),并等待任務運作結束。

綜合上面的描述,這裡給出mapreduce任務初始化以及送出運作的一般代碼,如代碼清單2-25所示。

在實際應用程式中,一般是直接從應用程式送出任務到hadoop叢集的,而非使用yarn jar的方式送出jar包來運作算法的。這裡給出通用的送出應用程式到hadoop叢集的代碼作為參考,不過在此之前需要簡要分析下configuration這個類。

configuration是hadoop系統的基礎公共類,可以通過這個類的api加載配置資訊,同時在初始化這個類的執行個體的時候也可以設定hadoop叢集的配置,進而直接針對某個hadoop叢集送出任務,其api如圖2-34所示。

《Hadoop與大資料挖掘》一2.4.2 MapReduce原理

configuration各種set api中用得比較多的還是第1個,通用的送出應用程式到hadoop叢集的代碼也是使用的第1個,見代碼清單2-26。

上面的值需要根據實際的hadoop叢集對應配置進行修改。

同時,通過configuration的set方法也可以實作在mapper和reducer任務之間資訊共享。比如在driver中設定一個參數number,在mapper或reducer中取出該參數,如代碼清單2-27所示(注意,在mapreduce程式中是不能通過全局static變量擷取值的,這點需要特别注意)。

(2)mapper分析

對于使用者來說,其實比較關心的是mapper的map函數以及reducer的reduce函數,這裡先分析mapper的map函數,如代碼清單2-28所示。

1)自定義mapper需要繼承mapper,同時需要設定輸入輸出鍵值對格式,其中輸入鍵值對格式是與輸入格式設定的類讀取生成的鍵值對格式比對,而輸出鍵值對格式需要與driver中設定的mapper輸出的鍵值對格式比對。

2)mapper有3個函數,分别是setup、map、cleanup,其中實作setup、cleanup函數不是必須要求,mapper任務啟動後首先執行setup函數,該函數主要用于初始化工作;針對每個鍵值對會執行一次map函數,所有鍵值對處理完成後會調用cleanup函數,主要用于關閉資源等操作。

3)實作的map函數就是與實際業務邏輯挂鈎的代碼,主要由使用者編寫,這裡是單詞計數程式,是以這裡的邏輯是把每個鍵值對(鍵值對組成為:<行的偏移量,行字元串>)的值(也就是行字元串)按照空格進行分割,得到每個單詞,然後輸出每個單詞和1這樣的鍵值對。

(3)reducer分析

reducer針對mapper的輸出進行整合,同時輸入給reducer的是鍵值對組,是以其實reducer中的reduce函數就是針對每個鍵的所有彙總值的處理。reducer代碼如代碼清單2-29所示。

1)自定義reducer同樣需要繼承reducer,與mapper相同,需要設定輸入輸出鍵值對格式,這裡的輸入鍵值對格式需要與mapper的輸出鍵值對格式保持一緻,輸出鍵值對格式需要與driver中設定的輸出鍵值對格式保持一緻。

2)reducer也有3個函數:setup、cleanup、reduce,其中setup、cleanup函數其實和mapper的同名函數功能一緻,并且也是setup函數在最開始執行一次,而cleanup函數在最後執行一次。

3)使用者一般比較關心reduce函數的實作,這個函數裡面寫的就是與業務相關的處理邏輯了,比如,這裡單詞計數,就針對相同鍵,把其值的清單全部加起來進行輸出。

繼續閱讀