Hadoop中卖陵,Mapper和Reducer究竟背著我們做了什么?

在這篇文章中张峰,我們會(huì)探究泪蔫,Mapper和Reducer的一些不為人知的秘密。

為什么說(shuō)不為人知呢喘批?畢竟Hadoop是開源的鸥滨,你可以閱讀源碼獲取一切你想要的信息。你要是這樣做谤祖,我無(wú)法反駁,因?yàn)檫@確實(shí)是最權(quán)威的方式老速。

在閱讀《Hadoop: The Definitive Guide 4th Edition》時(shí)粥喜,我們都見過(guò)這么一副圖片,它簡(jiǎn)單的解釋了Mapper和Reducer究竟是如何溝通的橘券,究竟做了些什么:

盡管這幅圖片確實(shí)非常正確额湘,但是,很遺憾的是旁舰,它并不是非常詳細(xì)锋华。

至少在我閱讀這本書的時(shí)候,當(dāng)時(shí)看到這幅圖片箭窜,只能大致了解一下過(guò)程毯焕,而對(duì)一些細(xì)節(jié)并不是非常清楚。只有在后來(lái)搞明白了,再回來(lái)看這幅圖片纳猫,才覺得確實(shí)非常正確婆咸。

所以,在這篇文章中芜辕,我們會(huì)用具體的例子尚骄,來(lái)一步步地解析這個(gè)過(guò)程。

但是侵续,有一點(diǎn)需要各位注意的是倔丈,我只是用例子一步步地驗(yàn)證了這個(gè)過(guò)程,而并不是閱讀源碼來(lái)得出了這個(gè)過(guò)程状蜗。盡管實(shí)踐是檢驗(yàn)真理的唯一標(biāo)準(zhǔn)需五,但是在并不清楚真理是什么而靠實(shí)踐得到的結(jié)果來(lái)總結(jié)真理的情況下,并不是那么嚴(yán)格诗舰,可能會(huì)有一些偏差警儒。

所以,各位要做好一個(gè)心理準(zhǔn)備眶根,就是這篇文章中的內(nèi)容蜀铲,可能有錯(cuò)誤,各位要有一個(gè)質(zhì)疑的思想属百。

最近我也是打算閱讀Hadoop的源碼的记劝,到時(shí)也會(huì)通過(guò)源碼來(lái)驗(yàn)證這個(gè)過(guò)程是否正確。

那我們開始吧族扰。

總體輪廓

盡管上面我們已經(jīng)給了一副圖片厌丑,但是我還是總結(jié)了一副我認(rèn)為更加直觀的圖片,呈現(xiàn)給大家渔呵。

下面我們就會(huì)一一介紹為何他們他們是這個(gè)順序怒竿。

問(wèn)題

我們會(huì)用兩個(gè)問(wèn)題來(lái)闡述,如果搞懂這兩個(gè)問(wèn)題的處理過(guò)程扩氢,這個(gè)過(guò)程也就懂了耕驰。

問(wèn)題一:?jiǎn)卧~計(jì)數(shù)器。統(tǒng)計(jì)有相同首字母的單詞中录豺,全部的單詞的個(gè)數(shù)朦肘,以及不重復(fù)的單詞的個(gè)數(shù)。比如双饥,有(a, aa, aa, bb, ba),那么輸出應(yīng)該是(a, 3, 2), (b, 2, 2)媒抠。其中每個(gè)元組中的第二列為全部單詞的數(shù)量,第三列為不重復(fù)單詞的數(shù)量咏花。

問(wèn)題二:?jiǎn)卧~計(jì)數(shù)器趴生。跟上面的問(wèn)題大體相同,只是現(xiàn)在是統(tǒng)計(jì)有相同尾字母的單詞中,全部的單詞的個(gè)數(shù)冲秽,以及不重復(fù)的單詞的個(gè)數(shù)舍咖。還是上面的那個(gè)例子,現(xiàn)在輸出應(yīng)該是(a, 4, 3), (b, 1, 1)锉桑。

過(guò)程

問(wèn)題一

我們先來(lái)解決第一個(gè)問(wèn)題排霉。

很顯然,我們要是把單詞按照首字母分組民轴,那么就跟傳統(tǒng)的單詞計(jì)數(shù)器類似了攻柠。

所以,我們寫一個(gè)Partitioner后裸,將單詞們按照首字母分區(qū)瑰钮,保證首字母相同的單詞會(huì)被分到同一個(gè)Reducer中。

Partitioner的實(shí)現(xiàn)跟HashPartitioner的實(shí)現(xiàn)類似微驶,如下所示:

很簡(jiǎn)單對(duì)吧浪谴。

然后我們的Reducer端處理過(guò)程如下:

你可能很奇怪,為什么我們明明可以用HashSet來(lái)統(tǒng)計(jì)不重復(fù)單詞因苹,而偏偏要采用這種形式苟耻。

因?yàn)槿绻捎肏ashSet,就不會(huì)理解它排序的過(guò)程扶檐。

我們可以看到凶杖,我們?cè)赗educer端,就是判斷一下是否前一個(gè)分區(qū)已經(jīng)處理完畢款筑,如果已經(jīng)處理完智蝠,那么就將結(jié)果寫入到輸出中。最后在cleanup()函數(shù)中奈梳,再寫一遍杈湾,防止最后一個(gè)分區(qū)的結(jié)果被漏掉。

那么我們?yōu)槭裁纯梢赃@樣處理呢攘须?

因?yàn)槲覀兊膍apper的輸出如下:
(a, 1), (aa, 1), (aa, 1), (bb, 1), (ba, 1)

然后經(jīng)過(guò)Partitioner之后漆撞,產(chǎn)生了這么兩個(gè)Partition:

  • Partition 1: (a, 1), (aa, 1), (aa, 1)
  • Partition 2: (bb, 1), (ba, 1)

然后分別兩個(gè)Reducer來(lái)處理他們。當(dāng)然阻课,如果你強(qiáng)制只有一個(gè)Reducer,那么它們還是會(huì)被同一個(gè)Reducer處理艰匙。所以才有了我們?cè)赗educer中判斷上一個(gè)Partition是否處理完畢的邏輯限煞。

數(shù)據(jù)在Reducer端會(huì)先進(jìn)行一個(gè)排序,那么它是如何進(jìn)行排序的呢员凝?

默認(rèn)情況下署驻,是按照Key以及其類型進(jìn)行排序。這里我們的Key的類型為Text,所以會(huì)將這個(gè)Reducer接收到的數(shù)據(jù)按照Text類型的Comparator進(jìn)行排序旺上。

我們這里假設(shè)僅有一個(gè)Reducer瓶蚂。

由于TextComparator會(huì)將輸入排序成(a, 1), (aa, 1), (aa, 1), (ba, 1), (bb, 1)這種順序,所以上面的代碼沒有什么問(wèn)題宣吱。

而你需要注意的是窃这,如果你用的是自定義的類型,或者自定義的Comparator征候,那么經(jīng)過(guò)排序后杭攻,可能是亂序的,可能以a開頭的單詞和以b開頭的單詞就是亂序的了疤坝。具體的例子兆解,我們會(huì)在下一個(gè)問(wèn)題中介紹到。

然后跑揉,Reducer端會(huì)進(jìn)行merge操作锅睛,會(huì)將(a, 1), (aa, 1), (aa, 1), (ba, 1), (bb, 1)merge為((a, 1), (aa, (1, 1)), (ba, 1), (bb, 1))

這樣看历谍,我們的Reducer是正確的现拒。

但是這里同樣有一個(gè)坑。

你怎么知道它是如何進(jìn)行merge的扮饶?

這個(gè)問(wèn)題具练,我們也會(huì)在問(wèn)題二中介紹。

現(xiàn)在你只需要清楚甜无,它也是按照Text進(jìn)行merge的就好了扛点。

Ok。那結(jié)果自然是正確的岂丘。

問(wèn)題二

問(wèn)題二看起來(lái)好像跟問(wèn)題一類似陵究?

對(duì)的。

跟問(wèn)題一的區(qū)別是奥帘,我們需要對(duì)尾字母進(jìn)行分區(qū)铜邮?

Yes。

所以其實(shí)有一個(gè)很簡(jiǎn)單的解決這個(gè)問(wèn)題的方式寨蹋,即把尾字母提到前面去松蒜,成為首字母,然后這個(gè)問(wèn)題就跟問(wèn)題一一樣了已旧,類似于動(dòng)態(tài)規(guī)劃秸苗。對(duì)吧?

但是這里我們不采用這種方法运褪。因?yàn)檫@種方法對(duì)我們理解在問(wèn)題一中提到的惊楼,Reducer端如何進(jìn)行排序玖瘸,如何進(jìn)行merge并沒有幫助。

我們采用另一種方法檀咙。

還是對(duì)尾字母進(jìn)行排序雅倒。

然后我們的Partitioner如下:

Reducer如下:

你會(huì)發(fā)現(xiàn),當(dāng)你的Reducer的數(shù)量大于或者等于你的Partition的數(shù)量時(shí)弧可,everything works well蔑匣。但是一旦你只有一個(gè)Reducer,就出現(xiàn)問(wèn)題了侣诺。

為什么呢殖演?

我們上面提到過(guò),Reducer端會(huì)將收到的數(shù)據(jù)先按照Key以及Key的對(duì)應(yīng)的類型的Comparator進(jìn)行排序年鸳。

假設(shè)它收到了這么兩個(gè)Partition的數(shù)據(jù):

  • Partition 1: (aa, 1), (ba, 1),
  • Partition 2: (bb, 1), (ab, 1)

我們希望它如何排序趴久?

(aa, 1), (ba, 1), (ab, 1), (bb, 1)

反正就是相同尾字母的單詞都是相鄰的。

而實(shí)際上搔确,它會(huì)按照TextComparator進(jìn)行排序彼棍,那么排序的結(jié)果是什么呢?

(aa, 1), (ab, 1), (ba, 1), (bb, 1)

那結(jié)果自然是不正確膳算。

為什么你的Reducer的數(shù)量大于或者等于你的Partition的數(shù)量時(shí)座硕,Everything works well呢?我想你應(yīng)該已經(jīng)有答案了涕蜂。

好华匾,找到問(wèn)題所在了。那我們自然就想到解決方案机隙,我們自己定義一個(gè)排序函數(shù)不就好了蜘拉?

Yes.

所以我們自定義了一個(gè)數(shù)據(jù)類型,以及一個(gè)對(duì)應(yīng)的Comparator有鹿。其實(shí)我這里寫的有些麻煩了旭旭,不用自定義數(shù)據(jù)類型的。各位自己寫的時(shí)候要注意葱跋。

我們可以看到持寄,在SuffixCompareTextcompare(SuffixCompareText o)中,會(huì)先根據(jù)尾字母進(jìn)行排序娱俺,如果尾字母相同稍味,則根據(jù)剩下的字符串進(jìn)行排序。

這樣我們不僅能保證具有相同尾字母的單詞是連續(xù)的荠卷,還能保證具有相同尾字母且相同的單詞也是連續(xù)的模庐。

為什么需要這種保證呢?

因?yàn)閙erge僵朗。

現(xiàn)在是時(shí)候介紹一下merge的過(guò)程了赖欣。

  • 首先查找你是否通過(guò)Job.setGroupComparatorClass(YourComparatorClass)方法指定了merge的方法,如果有验庙,則根據(jù)這個(gè)方法顶吮,對(duì)輸入的相鄰的數(shù)據(jù)進(jìn)行比較,如果相同粪薛,則合并悴了。注意,是相鄰的數(shù)據(jù)违寿。比如湃交,如果輸入數(shù)據(jù)是(aa, 1), (aa, 1), (ab, 1),則會(huì)被合并為(aa, (1, 1)), (ab, 1)藤巢。而如果輸入數(shù)據(jù)是(aa, 1), (ab, 1), (aa, 1)搞莺,則并不會(huì)進(jìn)行合并,結(jié)果還是(aa, 1), (ab, 1), (aa, 1)掂咒。
  • 如果你沒有指定這個(gè)方法才沧,那么就查看你是否通過(guò)Job.setSortComparatorClass(SortComparatorClass)指定了對(duì)數(shù)據(jù)排序的方法,如果指定了的話绍刮,那么會(huì)根據(jù)這個(gè)方法温圆,對(duì)輸入的相鄰的數(shù)據(jù)進(jìn)行比較,如果相同孩革,則合并岁歉。所以,你可以看到膝蜈,如果上面的SuffixCompareTextcompare中不注明當(dāng)尾字母相同時(shí)锅移,對(duì)剩下的字符串進(jìn)行比較。那么彬檀,(ab, 1), (cb, 1), (bb, 1)會(huì)被合并為(ab, (1, 1, 1))帆啃。因?yàn)樵?strong>compare()方法中,它們比較的結(jié)果為0窍帝,即相同努潘。這樣我們就無(wú)法統(tǒng)計(jì)不重復(fù)單詞的數(shù)量了。
  • 如果你上面的兩個(gè)方法都沒有指定坤学,那么就根據(jù)你的Reducer的input的Key進(jìn)行合并疯坤。也是根據(jù)Key的Comparator

其實(shí)不管怎么說(shuō)深浮,由于merge時(shí)压怠,是對(duì)相鄰的數(shù)據(jù)進(jìn)行對(duì)比的,所以你一定需要讓Reducer拿到的數(shù)據(jù)是有序的飞苇。

這里似乎GroupComparator沒有什么用菌瘫,因?yàn)槲覀兊妮斎氲捻樞蛞呀?jīng)是有序的了蜗顽。但是,理解它的過(guò)程雨让,也是有一些好處的雇盖。比如,萬(wàn)一以后你不僅僅只是想按照相同的key進(jìn)行merge呢栖忠?

總結(jié)

在上文中崔挖,我們已經(jīng)解密了mapper到reducer的過(guò)程。理解這些對(duì)你以后會(huì)大有裨益的庵寞。

源碼

關(guān)于這個(gè)Demo的源碼狸相,我已經(jīng)發(fā)布到Github上了,點(diǎn)擊這里捐川。

你也可以復(fù)制這個(gè)鏈接到瀏覽器來(lái)查看脓鹃。
https://github.com/AlstonWilliams/WordCountForHadoop

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市古沥,隨后出現(xiàn)的幾起案子将谊,更是在濱河造成了極大的恐慌,老刑警劉巖渐白,帶你破解...
    沈念sama閱讀 218,122評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件尊浓,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡纯衍,警方通過(guò)查閱死者的電腦和手機(jī)栋齿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)襟诸,“玉大人瓦堵,你說(shuō)我怎么就攤上這事「枨祝” “怎么了菇用?”我有些...
    開封第一講書人閱讀 164,491評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)陷揪。 經(jīng)常有香客問(wèn)我惋鸥,道長(zhǎng),這世上最難降的妖魔是什么悍缠? 我笑而不...
    開封第一講書人閱讀 58,636評(píng)論 1 293
  • 正文 為了忘掉前任卦绣,我火速辦了婚禮,結(jié)果婚禮上飞蚓,老公的妹妹穿的比我還像新娘滤港。我一直安慰自己,他們只是感情好趴拧,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評(píng)論 6 392
  • 文/花漫 我一把揭開白布溅漾。 她就那樣靜靜地躺著山叮,像睡著了一般。 火紅的嫁衣襯著肌膚如雪添履。 梳的紋絲不亂的頭發(fā)上聘芜,一...
    開封第一講書人閱讀 51,541評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音缝龄,去河邊找鬼。 笑死挂谍,一個(gè)胖子當(dāng)著我的面吹牛叔壤,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播口叙,決...
    沈念sama閱讀 40,292評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼炼绘,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了妄田?” 一聲冷哼從身側(cè)響起俺亮,我...
    開封第一講書人閱讀 39,211評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎疟呐,沒想到半個(gè)月后脚曾,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,655評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡启具,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評(píng)論 3 336
  • 正文 我和宋清朗相戀三年本讥,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鲁冯。...
    茶點(diǎn)故事閱讀 39,965評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡拷沸,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出薯演,到底是詐尸還是另有隱情撞芍,我是刑警寧澤,帶...
    沈念sama閱讀 35,684評(píng)論 5 347
  • 正文 年R本政府宣布跨扮,位于F島的核電站序无,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏衡创。R本人自食惡果不足惜愉镰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望钧汹。 院中可真熱鬧丈探,春花似錦、人聲如沸拔莱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至讼渊,卻和暖如春动看,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背爪幻。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工菱皆, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人挨稿。 一個(gè)月前我還...
    沈念sama閱讀 48,126評(píng)論 3 370
  • 正文 我出身青樓仇轻,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親奶甘。 傳聞我的和親對(duì)象是個(gè)殘疾皇子篷店,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評(píng)論 2 355