MR的shuffle發(fā)生在什么過程
shuffle主要發(fā)生在 Map端的spill 和 reduce端sort,copy過程
Map端: 在Map端會(huì)發(fā)生shuffle的階段主要是spill過程. map的輸出以KV的形式寫入一個(gè)叫KVbuffer的環(huán)形緩沖區(qū),kvbuffer包括kvmeta(記錄的是元數(shù)據(jù)信息)和kv(真正的信息),當(dāng)緩沖區(qū)的數(shù)量值達(dá)到閾值(默認(rèn)為80%),溢出行為會(huì)在一個(gè)后臺(tái)開啟一個(gè)sortAndSpill線程,然后開始寫數(shù)據(jù),在磁盤上會(huì)產(chǎn)生一個(gè)索引文件和一個(gè)數(shù)據(jù)文件(分區(qū)且有序的),這就是spill過程宙彪。注: 臨界值(80%)會(huì)被觸發(fā),但是不會(huì)阻塞
reduce端: reduce端主要包括sort過程和copy過程. reduce的數(shù)據(jù)都是從map端過來的,且是分區(qū)有序的,先map后reduce,但是面對(duì)多個(gè)job,map和redcue是同時(shí)進(jìn)行的,一邊sort,一邊copy,同時(shí)進(jìn)行.會(huì)產(chǎn)生大量的io和內(nèi)存消耗,因此需要我們調(diào)優(yōu).
Map端優(yōu)化
原則: 避免寫入多個(gè)spill文件可能達(dá)到最好的性能有巧,一個(gè)spill文件是最好的
kvbuffer環(huán)形緩沖區(qū)
緩沖區(qū)的默認(rèn)大小是100M,可以通過mapreduce.task.io.sort.mb這個(gè)屬性來設(shè)置,具體配置得根據(jù)具體業(yè)務(wù)情景來分析. 一般不修改
緩沖區(qū)閾值
開始spill的Buffer比例默認(rèn)為80%释漆,可以通過mapreduce.map.sort.spill.percent設(shè)置,還得看具體業(yè)務(wù)情景,一般不修改
合并Spill文件
mapreduce.task.io.sort.factor屬性配置每次最多合并多少個(gè)文件,默認(rèn)為10,即一次最多合并10個(gè)spill文件.如果spill文件數(shù)量大于mapreduce.map.combiner.minspills配置的數(shù)篮迎,則在合并文件寫入之前男图,會(huì)再次運(yùn)行combiner。如果spill文件數(shù)量太少甜橱,運(yùn)行combiner的收益可能小于調(diào)用的代價(jià)逊笆。
對(duì)map輸出進(jìn)行壓縮
在數(shù)據(jù)量大的時(shí)候,可以對(duì)map輸出進(jìn)行壓縮,要啟用壓縮岂傲,將mapreduce.map.output.compress設(shè)為true难裆,并使用mapreduce.map.output.compress.codec設(shè)置使用的壓縮算法
Reduce端優(yōu)化
原則: 如果能夠讓所有數(shù)據(jù)都保存在內(nèi)存中,可以達(dá)到最佳的性能
copy線程數(shù)量
copy是用來從map任務(wù)中提取數(shù)據(jù)的,默認(rèn)為5個(gè)copy線程,可以通過mapreduce.reduce.shuffle.parallelcopies配置
內(nèi)存分配
如果能夠讓所有數(shù)據(jù)都保存在內(nèi)存中譬胎,可以達(dá)到最佳的性能差牛。通常情況下,內(nèi)存都保留給reduce函數(shù)堰乔,但是如果reduce函數(shù)對(duì)內(nèi)存需求不是很高,將mapreduce.reduce.merge.inmem.threshold(觸發(fā)合并的map輸出文件數(shù))設(shè)為0脐恩,mapreduce.reduce.input.buffer.percent(用于保存map輸出文件的堆內(nèi)存比例)設(shè)為1.0