map/reduce
過程的認識
最初我一直簡單的以為map
的工作就是將資料打散,而reduce
就是將map
打散後的資料合併。雖然之前跑過wordcount
的例子,但之前只是對輸出reduce
最終的結果感興趣,對控制台列印的日誌資訊完全不懂。這幾天我們團隊在探索pagerank
,才開始對map/reduce
有了深一層的了解。當乙個job
提交後,後續具體的一系列分配排程工作我現在不清楚。我現在只是了解些map/reduce
過程。
原來map
過程和reduce
的過程也都包含了多個步驟。
一.map 階段
作業的inputformat
類規定了對提交的作業的輸入檔案切分方法。預設是將輸入檔案按照位元組的大小分割成不同的塊。
至於這個過程到底是怎麼實現的我也不清楚。我現在只是記錄下我對map reduce
的理解。
輸入檔案可能會被打散成多個塊(block
),至於是怎麼分成塊的,我不清楚。乙個塊的大小是預設是64mb
,也是可以通過引數設定的其大小的。所以若採用預設的,如果初始資料<64mb
時,就只有乙個塊了。每乙個塊就是乙個map task
的輸入。也就是說有多少個塊就會有多少個map task
。那map task
的工作是怎麼樣的呢?
簡單的來說,map task
也有幾個步驟:從hdfs
上獲取block
資料à從記憶體中溢寫(spill
)檔案à
merge
溢寫檔案 1.
block
和map task
怎麼聯絡起來的呢。那些任務都是屬於作業提交後的初始化和排程問題了。我還沒有明白。第一步就先不說了,只能簡單的理解是map task
知道它的輸入資料(block
)在**,直接去取就可以了。
在datanode
節點上的每個map task
任務都會有乙個記憶體緩衝區,用來臨時儲存它的輸出結果的,其實也就是減少對磁碟的讀寫頻率。這裡面的資料只是key/value
對和partition
的結果。前者我們都可以理解是什麼東西,那後者呢?我們都知道map task
的數量不是完全由人為設定的,但reduce task
的數目是client
設定的,預設是1
。這就需要對key
值劃分區,知道哪些key
是由哪個reduce task
處理的。partitioner
就是幹這個工作的。預設的方法是使用hash
函式,當然使用者也可以通過實現自定義的partitioner
來控制哪個key
被分配給哪個reducer
。結果可能會出現多個key/value
對最終交由同乙個reduce task
去處理。針對這些key/value
對就需要合併了,合併是為了減小map
最終檔案在磁碟上的溢寫。至於這個合併到底是在哪個時期進行的,我也不清楚。 2.
當然這個緩衝區也是有大小限制的(預設是100mb
)。我們也可以通過某些屬性來設定這個具體大小。而如果map
的輸出結果很大,緩衝區容納不了時,必定要適時將緩衝區的資料寫在磁碟上(也稱為spill
過程)。預設為緩衝區的容量達到80%
時(當然可以去重新設定了),就將它寫入磁碟。如果等到緩衝區滿才開始這部分的工作,那在寫入磁碟的過程中,map
可能還要輸出資料,因為那個溢寫的過程是由單獨的執行緒控制的。那麼是否有可能會出現記憶體溢位?為了避免這種情況,這就需要前面所說的那個80%
的門限值了。而在這個溢寫過程也會對這些資料進行sort
,預設是使用快速排序對key
和partition
做排序。這些資料記錄本身是以什麼格式儲存在記憶體中的我還不清楚,所以也不明白到底是如何個快速排序法。
3.每次spill
過程寫入磁碟的資料是生成乙個單獨檔案的(
通常稱為溢寫檔案)
,這就又會出現map
真正執行完成後,如果是大資料量結果輸出,則會形成很多個溢寫檔案。那麼勢必又要將這些個檔案合併到一起。這個過程就稱為merge
了。至於每次merge
的溢寫檔案數目是可以通過引數設定的,但是我不知道是不是總的merge
次數是否也有限定,我現在還不清楚。
但是可能又會有疑問了,如果merge
只是簡單的合併過程,那如果像wordcount
例子的情況,假如第乙個溢寫檔案中單詞「hello
」(key
值) 出現的次數是4(value
值),第二個溢寫檔案中單詞「hello
」(key
值) 出現的次數是9(value
值),假設只有兩個溢寫檔案。那merge
後還是會出現相同的key
值鍵對。所以如果之前設定過combiner ,
此就會使用combiner
將相同的key
的values
合併,形成hello(key
值)---[4,9](values
值)。這個combine
過程並不一定要等到merge
結束後才執行,而且也並不是一定要執行,使用者可以自己設定的。當這些個步驟都結束後map
端的工作才算結束。最終的這個輸出檔案也是儲存在本地磁碟中的。
二.reduce階段
reduce
是將map
的輸出結果作為它的輸入檔案。整個reduce
過程就又涉及到多個步驟了。reduce
過程並不是要等到所有的map task
執行完後才執行。只要有乙個map task
執行完後,reduce
階段就可以開始了。
這個過程我只能用粗略圖表示了。
1.首先就是怎麼得到map
的輸出資料。在實際執行過程中map
的執行過程很可能和reduce
的執行過程不在同乙個節點(datanode
)上。那它們之間到底是怎麼聯絡的呢?它是通過http
方式請求jobtracker
獲取當前有哪些map task
任務已完成,然後從map task
所在的tasktracker
遠端獲取map task
的輸出檔案。但並不是map
的整個輸出檔案,而只是獲取由該reduce task
處理的那部分資料就可以了。 2.
,此時也會做這個工作。而對乙個reduce
來說,它的資料可能是多個map
。也就是說,即使reduce
所需要的資料是從很多個map
上的(若是大於設定的並行度),也只能一次並行的從設定的這麼多個map
我想不通的是這樣會不會太麻煩了點啊,多浪費網路資源啊。不過,我也不知道它們之間該使用什麼樣的資料傳輸會更好。 3.
copy
獲取到的資料首先也是放入到記憶體中的,也就是說這裡又出現了類似map
階段中的溢寫過程了,會產生溢寫檔案。所以在這裡就又有了merge
的過程了。使得最終形成乙個檔案。不過這個檔案有可能是在記憶體中,也有可能是在磁碟上了,預設是在磁碟上的。當最終檔案形成後,reduce
函式才開始執行。並將最終的結果寫到hdfs
上,至於這步是如何寫上去的,還不清楚。至此整個reduce
階段才算結束。在這裡還有明白的就是reduce後的結果並不是排序好的,而map 的最終資料是已經排好序的,且已經是分好區的了。 三.
最後還有需要說明的是client可以控制對這些中間結果是否進行壓縮以及怎麼壓縮,使用哪種壓縮格式。也不是說一定要這個壓縮步驟,若需要寫入磁碟的資料量太大,相對來說就可以讓cpu幫忙減輕下io負荷。具體map reduce整個過程中有太多問題還不清楚,還要繼續驗證。總之就是越發覺得複雜了。
初步認識MapReduce
mapreduce是hadoop的一種分布式計算框架,用於大規模的平行計算。mapreduce的工作階段可以分為map階段和reduce階段,這也是mapreduce名字的由來,每乙個階段都是以鍵值對 key value 作為輸入和輸出。在實際程式設計中,底層的東西框架已經幫我們寫好了,我們只要定義...
Map Reduce的過程解析
map reduce的過程首先是由客戶端提交乙個任務開始的。提交任務主要是通過jobclient.runjob jobconf 靜態函式實現的 public static runningjob runjob jobconf job throws ioexception finally finally...
Map Reduce過程概述
map reduce的過程首先是由客戶端提交乙個任務開始的。提交任務主要是通過jobclient.runjob jobconf 靜態函式實現的 public static runningjob runjob jobconf job throws ioexception finally finally...