MapReduce工作流程
原始數(shù)據(jù)File
1T數(shù)據(jù)被切分成塊存放在HDFS上,每一個(gè)塊有128M大小
數(shù)據(jù)塊Block
hdfs上數(shù)據(jù)存儲(chǔ)的一個(gè)單元,同一個(gè)文件中塊的大小都是相同的
因?yàn)閿?shù)據(jù)存儲(chǔ)到HDFS上不可變,所以有可能塊的數(shù)量和集群的計(jì)算能力不匹配 我們需要一個(gè)動(dòng)態(tài)調(diào)整本次參與計(jì)算節(jié)點(diǎn)數(shù)量的一個(gè)單位
切片Split
切片是一個(gè)邏輯概念
在不改變現(xiàn)在數(shù)據(jù)存儲(chǔ)的情況下,可以控制參與計(jì)算的節(jié)點(diǎn)數(shù)目 通過切片大小可以達(dá)到控制計(jì)算節(jié)點(diǎn)數(shù)量的目的
有多少個(gè)切片就會(huì)執(zhí)行多少個(gè)Map任務(wù)
一般切片大小為Block的整數(shù)倍(2 1/2)
防止多余創(chuàng)建和很多的數(shù)據(jù)連接
如果Split>Block ,計(jì)算節(jié)點(diǎn)少了
如果Split<Block ,計(jì)算節(jié)點(diǎn)多了
默認(rèn)情況下,Split切片的大小等于Block的大小 ,默認(rèn)128M 一個(gè)切片對(duì)應(yīng)一個(gè)MapTask
MapTask
map默認(rèn)從所屬切片讀取數(shù)據(jù),每次讀取一行(默認(rèn)讀取器)到內(nèi)存中
我們可以根據(jù)自己書寫的分詞邏輯(空格分隔).計(jì)算每個(gè)單詞出現(xiàn)的次數(shù) 這是就會(huì)產(chǎn)生 (Map<String,Integer>)臨時(shí)數(shù)據(jù),存放在內(nèi)存中
但是內(nèi)存大小是有限的,如果多個(gè)任務(wù)同時(shí)執(zhí)行有可能內(nèi)存溢出(OOM) 如果把數(shù)據(jù)都直接存放到硬盤,效率太低
我們需要在OOM和效率低之間提供一個(gè)有效方案
可以現(xiàn)在內(nèi)存中寫入一部分,然后寫出到硬盤
環(huán)形數(shù)據(jù)緩沖區(qū)
可以循環(huán)利用這塊內(nèi)存區(qū)域,減少數(shù)據(jù)溢寫時(shí)map的停止時(shí)間
每一個(gè)Map可以獨(dú)享的一個(gè)內(nèi)存區(qū)域
在內(nèi)存中構(gòu)建一個(gè)環(huán)形數(shù)據(jù)緩沖區(qū)(kvBuffer),默認(rèn)大小為100M
設(shè)置緩沖區(qū)的閾值為80%,當(dāng)緩沖區(qū)的數(shù)據(jù)達(dá)到80M開始向外溢寫到硬盤
溢寫的時(shí)候還有20M的空間可以被使用效率并不會(huì)被減緩 而且將數(shù)據(jù)循環(huán)寫到硬盤,不用擔(dān)心OOM問題
分區(qū)Partation
根據(jù)Key直接計(jì)算出對(duì)應(yīng)的Reduce
分區(qū)的數(shù)量和Reduce的數(shù)量是相等的
hash(key) % partation = num
默認(rèn)分區(qū)的算法是Hash然后取余
Object的hashCode()---equals()
如果兩個(gè)對(duì)象equals,那么兩個(gè)對(duì)象的hashcode一定相等
如果兩個(gè)對(duì)象的hashcode相等,但是對(duì)象不一定equlas
排序Sort
對(duì)要溢寫的數(shù)據(jù)進(jìn)行排序(QuickSort)
按照先Partation后Key的順序排序-->相同分區(qū)在一起,相同Key的在一起
我們將來溢寫出的小文件也都是有序的
溢寫Spill
將內(nèi)存中的數(shù)據(jù)循環(huán)寫到硬盤,不用擔(dān)心OOM問題
每次會(huì)產(chǎn)生一個(gè)80M的文件
如果本次Map產(chǎn)生的數(shù)據(jù)較多,可能會(huì)溢寫多個(gè)文件
合并Merge
因?yàn)橐鐚憰?huì)產(chǎn)生很多有序(分區(qū) key)的小文件,而且小文件的數(shù)目不確定
后面向reduce傳遞數(shù)據(jù)帶來很大的問題
所以將小文件合并成一個(gè)大文件,將來拉取的數(shù)據(jù)直接從大文件拉取即可
合并小文件的時(shí)候同樣進(jìn)行排序(歸并排序),最終產(chǎn)生一個(gè)有序的大文件
組合器combiner
集群的帶寬限制了mapreduce作業(yè)的數(shù)量,因此應(yīng)該盡量避免map和reduce任務(wù)之間的數(shù)據(jù)傳 輸。hadoop允許用戶對(duì)map的輸出數(shù)據(jù)進(jìn)行處理,用戶可自定義combiner函數(shù)(如同map函數(shù)和 reduce函數(shù)一般),其邏輯一般和reduce函數(shù)一樣,combiner的輸入是map的輸出,combiner 的輸出作為reduce的輸入,很多情況下可以直接將reduce函數(shù)作為conbiner函數(shù)來使用
(job.setCombinerClass(FlowCountReducer.class);)。
combiner屬于優(yōu)化方案,所以無(wú)法確定combiner函數(shù)會(huì)調(diào)用多少次,可以在環(huán)形緩存區(qū)溢出文件 時(shí)調(diào)用combiner函數(shù),也可以在溢出的小文件合并成大文件時(shí)調(diào)用combiner。但要保證不管調(diào)用 幾次combiner函數(shù)都不會(huì)影響最終的結(jié)果,所以不是所有處理邏輯都可以使用combiner組件,有 些邏輯如果在使用了combiner函數(shù)后會(huì)改變最后rerduce的輸出結(jié)果(如求幾個(gè)數(shù)的平均值,就不 能先用combiner求一次各個(gè)map輸出結(jié)果的平均值,再求這些平均值的平均值,這將導(dǎo)致結(jié)果錯(cuò) 誤)。
combiner的意義就是對(duì)每一個(gè)maptask的輸出進(jìn)行局部匯總,以減小網(wǎng)絡(luò)傳輸量。
原先傳給reduce的數(shù)據(jù)是 a1 a1 a1 a1 a1
第一次combiner組合之后變?yōu)閍{1,1,1,1,..}
第二次combiner后傳給reduce的數(shù)據(jù)變?yōu)閍{4,2,3,5...}
拉取Fetch
我們需要將Map的臨時(shí)結(jié)果拉取到Reduce節(jié)點(diǎn)
原則:
相同的Key必須拉取到同一個(gè)Reduce節(jié)點(diǎn)
但是一個(gè)Reduce節(jié)點(diǎn)可以有多個(gè)Key
未排序前拉取數(shù)據(jù)的時(shí)候必須對(duì)Map產(chǎn)生的最終的合并文件做全序遍歷
而且每一個(gè)reduce都要做一個(gè)全序遍歷
如果map產(chǎn)生的大文件是有序的,每一個(gè)reduce只需要從文件中讀取自己所需的即可
合并Merge
因?yàn)閞educe拉取的時(shí)候,會(huì)從多個(gè)map拉取數(shù)據(jù)
那么每個(gè)map都會(huì)產(chǎn)生一個(gè)小文件,這些小文件(文件與文件之間無(wú)序,文件內(nèi)部有序) 為了方便計(jì)算(沒必要讀取N個(gè)小文件),需要合并文件
歸并算法合并成2個(gè)
相同的key都在一起
歸并Reduce
將文件中的數(shù)據(jù)讀取到內(nèi)存中
一次性將相同的key全部讀取到內(nèi)存中
直接將相同的key得到結(jié)果-->最終結(jié)果文章來源:http://www.zghlxwxcb.cn/news/detail-515242.html
寫出Output
每個(gè)reduce將自己計(jì)算的最終結(jié)果都會(huì)存放到HDFS上文章來源地址http://www.zghlxwxcb.cn/news/detail-515242.html
到了這里,關(guān)于MapReduce分布式計(jì)算(二)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!