MapReduce的shuffle過程詳解
馬克-to-win @ 馬克java社區(qū):思路的精髓:想象一下,你把前面那個文件的三行字兒,分別發(fā)給你三個同學(xué),但他們都不知道別人手上的字是什么,他們只能搞清自己手上的字,每個出現(xiàn)多少次?最后你必須得把他們?nèi)齻€人手中的結(jié)果統(tǒng)一在一起,結(jié)果才會正確,最聰明的辦法就是排序和融合,比如hello,在第一個人手里出現(xiàn)兩次,第二個人手里出現(xiàn)一次,三個人最后開個會, 一統(tǒng)一信息(對于mapreduce來講就是一個partition數(shù)據(jù)集中到一個文件中 ),信息就透明了。對于咱們例子當(dāng)中,hello,出現(xiàn)了四次。但現(xiàn)在想成這三個人是啞巴,而不是聾子, 可執(zhí)行命令,但自己不能發(fā)命令,這是和機器最貼切的比喻。 機器不能像人一樣溝通, 但用排序和融合這樣的指令,就逼著結(jié)果就出來了。 只有通過排序和融合,才能知道這件事。馬克- to-win:馬克 java社區(qū):防盜版實名手機尾號: 73203。
shuffle的英文是洗牌,混洗的意思,洗牌就是越亂越好的意思。當(dāng)在集群的情況下是這樣的,假如有三個map節(jié)點和三個reduce節(jié)點,一號reduce節(jié)點的數(shù)據(jù)會來自于三個map節(jié)點,而不是就來自于一號map節(jié)點。所以說它們的數(shù)據(jù)會混合,路線會交叉, 3叉3。想象一下,像不像洗牌? 馬克-to-win @ 馬克java社區(qū):shuffle在MapReduce中是指map輸出后到reduce接收前,按下面的官方shuffle圖:具體可以分為map端和reduce端兩個部分。在最開始,假設(shè)我們就提交一個大文件,MapReduce會對要處理的大文件數(shù)據(jù)進(jìn)行分片(split)操作放到多臺機器的集群里,(想象一個搬走大山的大活給一個師的人馬,是不是要把人,部署一圈,展開,一人干一塊兒,一個成語叫螞蟻搬家,精髓在于拆?,F(xiàn)在是一樣的道理。現(xiàn)在你要擺弄一個1.5T的文件, 需要先把它切開, 分配到不同機器)為每一個分片分配一個MapTask任務(wù),接下來會對每一個分片中的每一行數(shù)據(jù)進(jìn)行處理,得到鍵值對(key,value),其中key為偏移量,value為一行的內(nèi)容。準(zhǔn)備給咱們的自己的map方法。執(zhí)行完咱自己的map方法,便進(jìn)入shuffle階段。馬克-to-win @ 馬克java社區(qū):為提高效率,mapreduce會把我們的寫出的結(jié)果先存儲到map節(jié)點的“環(huán)形內(nèi)存緩沖區(qū)”(不深入探討),當(dāng)寫入的數(shù)據(jù)量達(dá)到預(yù)先設(shè)置的闕值后(默認(rèn)80%)便會啟動溢出(spill)線程將緩沖區(qū)中的那部分?jǐn)?shù)據(jù)溢出寫(spill)到磁盤的臨時文件中,可能會產(chǎn)生很多,并在寫入前根據(jù)key進(jìn)行排序(sort)和合并(combine,本章不討論)。馬克-to-win @ 馬克java社區(qū):當(dāng)我們map任務(wù)完成溢出寫后,mapreduce會對磁盤中這個map任務(wù)產(chǎn)生的所有臨時spill文件中的相同partition(本章不講, 本章只講一個partition,即一個reducer的情況)合并到一起,并對各個partition中的數(shù)據(jù)再次排序(sort),生成最終的文件,即生成key和對應(yīng)的value-list。馬克-to-win @ 馬克java社區(qū):之后, reduce task在執(zhí)行我們的reduce方法之前的工作就是不斷地拉取所有節(jié)點的map task的最終結(jié)果,然后不斷地做merge,最后合并成相對于一個分區(qū)的大文件(如果拉取的所有map數(shù)據(jù)總量都沒有超過內(nèi)存緩沖區(qū)大小,則數(shù)據(jù)就只存在于內(nèi)存中),然后按key做sort排序(無論這個過程發(fā)生在內(nèi)存還是磁盤,Reduce shuffle過程會輸出一個有序merged的數(shù)據(jù)塊。),排序之后緊接著分組(本章不講,就是一組),分組完成后才將整個文件交給我們的reduce方法處理。
馬克-to-win:上圖是shuffle的官方流程圖:
我們的實驗是在一臺機器上做的,即一個節(jié)點,但按照一個三臺集群來講, 也是可以的,現(xiàn)在假設(shè)三行文字在三臺不同的機器上。
節(jié)點1:
輸入:“hello a hello win”
輸出:(hello,1),(a,1),(hello,1),(win,1)
放在下圖的1位置的數(shù)據(jù)為排序且merged:(a,1),<"hello",<1,1>>,(win,1),之后被拉取到2位置。
節(jié)點2:
輸入:“hello a to”
輸出:(hello,1),(a,1),(to,1)
放在下圖的1位置的數(shù)據(jù)為排序且merged:(a,1),(hello,1),(to,1),之后被拉取到3位置。
節(jié)點3:
輸入:“hello mark”
輸出:(hello,1),(mark,1)
放在下圖的1位置的數(shù)據(jù)為排序且merged:(hello,1),(mark,1),之后被拉取到4位置。
在2,3,4位置經(jīng)過marge,最終一種結(jié)果可能是:位置5是<"a",<1,1>>,<"hello",<1,1,1,1>>,6是(mark,1),(to,1),(win,1)或者是:位置5是 <"a",<1,1>>,6是:<"hello",<1,1,1,1>>,(mark,1),(to,1),(win,1),或者是其他結(jié)果,都無所謂,(為什么無所謂? 因為無論中間過程怎么樣?結(jié)果都一樣) 因為最終還會merge成一個文件,是sorted。<"a",<1,1>>,<"hello",<1,1,1,1>>,(mark,1),(to,1),(win,1)
以下圖片來自于hadoop官網(wǎng)。意思很清楚,很有助于大家理解。