MapReduce 初識

MapReduce是一種大數據處理編程模型,它的思想來源於Google的幾篇論文,可以把它理解爲:把一堆混亂的數據按照某種特徵歸納起來,然後處理並得到結果。Map面對的是雜亂無章的互不相關的數據,它解析每個數據,從中提取出key和value,也就是提取數據的特徵。經過MapReduce的shuffle階段之後,在Reduce階段看到的都是已經歸納好的數據了,在此基礎上我們做進一步的處理,便得到了最終的結果。

Map and Reduce

MapReduce分爲兩個階段:map階段和reduce階段,每個階段都有一個鍵值對(key - value pair)作爲輸入、輸出,輸入輸出的類型需有開發人員指定。在開發時,需要編寫map函數和reduce函數。下面看下MapReduce是怎麼工作的。

Data Flow(數據流程)

首先,MapReduce Job是客戶端的執行任務的工作單元,它包含輸入數據、MapReduce程序、配置信息等。每個MapReduce Job又被分爲若干task,每個task又分爲map task 和 reduce task。這些task由YARN調度,並運行在集羣中的某些節點上,如果一個task失敗,它將會被重新調度到不同的節點上運行。

對於MapReduce Job的輸入數據,Hadoop會將輸入切分爲固定大小的塊,這個過程稱作“切片”(split)。Hadoop會爲每個切片創建一個map task,然後將切片作爲輸入,傳遞到用戶自定義的map函數中,供解析使用。

有多個切片意味着處理每個切片的時間要比處理整個輸入的時間要少,如果是並行處理切片,可以得到較好的負載均衡,因爲一個比較快的機器要比一個比較慢的機器處理的切片要多。但是,如果切片太小,就會增加管理切片和創建map task的開銷,進而影響整個job的執行時間。

那麼切片的大小爲多少比較好呢?

對於大多數job,切片的大小通常和HDFS塊的大小相同,默認爲128MB,當然切片的大小也可以改變,或是在創建文件的時候指定。

map任務的執行節點和輸入數據的存儲節點是同一個節點,那麼Hadoop的運行性能將達到最佳,因爲這不需要在節點間傳輸數據。這稱爲“數據本地化優化”。但有時,對於所有託管HDFS塊副本的節點,可能正在運行着其它的map task,這時,Job調度器將會首先在同一個機架上需找有空閒map task槽(free map slot)的節點,來運行task。如果在同一個機架上沒有找到,在另一個機架上找到了,這將導致在機架之間的網絡傳輸數據,降低效率。

下圖顯示了map task輸入數據源的三種可能性:



現在應該明白爲什麼最佳切片的大小應該和塊的大小相同:對map task來說,它是最大的輸入,可以保證被存儲在單個節點上。如果切片誇兩個塊,那麼HDFS的節點是不能存儲這兩個塊的(?),所以,對於這樣的塊必須通過網絡傳輸部分數據到運行map task的節點上。這與使用本地數據運行map任務相比,顯然要低效。

Map task將它的輸出寫到本地磁盤上,而不是HDFS。爲什麼這樣做?

Map的輸出是一箇中間輸出,還要被reduce任務處理產生最終的輸出,一旦job完成,map的輸出將會被刪除。所以,存放在HDFS中顯得有點大材小用。一旦在運行map任務的節點在map輸出之前失敗了,Hadoop將在另一個節點上自動運行map task,重新創建map輸出。

Reduce 任務並沒有數據本地化的優勢:一個單一Reduce task的輸入通常是所有map任務的輸出。因此,有序的map輸出必須通過網絡傳輸到reduce任務運行的節點,並在該節點進行合併,然後傳遞給用戶定義的reduce函數中。爲了可靠性,Reduce任務的輸出通常是存儲在HDFS中。對於HDFS中的reduce輸出塊,第一個副本是存放在本地節點,其它的副本存放在其它機架的節點中。因此,編寫reduce的輸出會佔用網絡帶寬,但僅僅是和HDFS的寫管道佔用的一樣多。

下圖是僅含有一個reduce任務的MapReduce的數據流程,虛線框表示節點,虛線箭頭表示數據在一個節點上的傳輸方向,實現箭頭表示數據在節點間的傳輸。



reduce任務的數量並不由切片的大小控制,而是可以單獨具體指定的。

當有多個reduce任務時,map任務會對它們的數據進行分區,每個分區對應一個reduce任務。在每個分區中包含有許多key(及其關聯的value),但是,對於給定的任意一個key只能存在於單個分區中。怎麼分區可以由用戶定義的分區函數來控制,但通常採用默認的分區方式:hash 函數

含有多個reduce任務的數據流程如下圖,該圖清晰的表明了在map任務和reduce任務之間的數據流爲什麼稱之爲“shuffle”(重新洗牌),這是因爲reduce任務的輸入是由多個map任務的輸出組成的。shuffle過程要比該圖顯示的更爲複雜,調整它可以對job的執行時間有較大的影響。


另外,也可以有0個reduce任務,當不需要shuffle時,這種情況也是可能的,因爲可以完全並行處理。在這種情況下,僅存在唯一的非本地節點的數據傳輸,那就是map任務的輸出寫到HDFS中。見下圖:


Combiner Functions

許多mapreduce job受限於集羣的網絡帶寬,所以要儘量減少map任務和reduce任務之間數據傳輸。Hadoop允許用戶在map任務的輸出上運行一個Combiner Functions,該函數的輸出作爲reduce函數的輸入。Combiner函數會在map輸出的基礎上,做進一步的合併處理來減少map和reduce任務間的傳輸量,起到優化的作用。但Hadoop並不保證對於某個map的輸出一定會調用combiner函數。不管怎樣,調用0次與調用多次combiner函數,reduce函數的最終結果應該是一樣的。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章