以示例程序
wordcount
爲例大數據
InputFormat
會將咱們指定的輸入路徑中的文件按照block
(默認 128M)邏輯切分紅若干切片(split
,若是文件不足 128M 則單獨爲一個切片,若是滿了128M可是不滿128M*1.1也單獨爲一個切片),而後交給RecordReader
進行處理,產出若干key/value record
code
產出的key/value record
會暫存在內存中的一塊環形緩衝區中(邏輯上成環形),寫入record
時會從環形上的兩個位置寫入,一個位置寫入record
,一個位置寫入record
的索引inde
,這樣作的好處是:要想在環上找到一個record
不用遍歷數據量較大的record
序列,而只用遍歷數據量較小的index
列表。orm
MapTask
會根據輸入的大數據源源不斷的產出record
,而環形緩衝的大小是有限的(假設是100M,此參數可配置),當環形緩衝的佔用量達到80%
(此參數可配置)時,就會對這80%
的record
進行一個全排序(準確的說是二次排序,先按照partition
有序(見Partitioner
),再按照record
的key
有序),若是你設置了CombinerClass
那麼同時會對record
進行一個合併,最後寫入磁盤(此過程稱爲溢寫),造成一個首先分區號有序其次key
有序的record
序列;而剩下的20%
則繼續迎接後續寫入的record
。cdn
這樣輸入的數據集就會分批次寫入到硬盤中,造成多個批次內有序的record
序列,而後再從硬盤中逐批讀出這些序列進行一個歸併排序(歸併的過程當中又能夠應用Combiner
作一個合併處理),最終產出該MapTask
對應的分區號有序、同一分區內record.key
有序的record
序列,即將流入Reducer
blog
MapTask
的數量是由切片規則來決定的,輸入的數據集會被切成多少片就會有多少個MapTask
,每一個MapTask
都會產出一個分區號有序的record
序列,而ReducerTask
是在Driver
中經過setNumReducerTask
手動指定的,通常會和Partitioner
返回的分區號(返回0則會由ReduceTask1
處理併產出到part-r-0000
)類別數保持一致。排序
ReduceTask
會從全部的MapTask
的產出中抓取出分區號和本身對應的record
過來,例如上圖中ReduceTask1
會分別抓取MapTask1
和MapTask2
產出的record
序列中分區號爲0
的部分,進行一個歸併排序(過程當中使用GroupingComparator
進行分組,結果對應Reducer#reduce
方法入參的Iterable values
)並將結果序列中的元素(Object key,Iterable values
)逐個交給Reducer#reduce
進行處理,能夠經過context.write
寫入到output
對應分區號的part-r-000x
中。索引