[老實李]MapReduce學(xué)習(xí)筆記

一、MapReduce應(yīng)用場景

Hadoop的Mapreduce是一個使用簡單的框架,基于它寫出來的程序可以運行在上千個商用機(jī)器組成的大型集群上,并以一種可靠容錯式并行處理TB級別的數(shù)據(jù)集。

MapReduce的優(yōu)缺點:

優(yōu)點:易于編程、良好的擴(kuò)展性、高容錯性、離線處理

缺點:無法實時計算、無法流式計算、不適合DAG(有向圖)計算

二、MapReduce的編程模型

1.MapReduce的執(zhí)行流程

假如有一批文件(規(guī)模為TB級或者PB級),我們要如何統(tǒng)計這些文件中所有單詞出現(xiàn)的次數(shù)?首先,我們要分別統(tǒng)計每個文件中單詞出現(xiàn)的次數(shù),然后,累加不同文件中同一單詞出現(xiàn)的次數(shù)。那么“首先”就是對應(yīng)的MapReduce的Map過程,“然后”對應(yīng)的就是MapReduce的Reduce過程。下面我們通過示意圖來分析MapReduce的過程。

image.png

上圖的流程大概分為以下幾步。

第一步:假設(shè)一個文件有三行英文單詞作為 MapReduce 的Input(輸入),這里經(jīng)過 Splitting 過程把文件分割為3塊。分割后的3塊數(shù)據(jù)就可以并行處理,每一塊交給一個 map 線程處理。

第二步:每個 map 線程中,以每個單詞為key,以1作為詞頻數(shù)value,然后輸出。

第三步:每個 map 的輸出要經(jīng)過 shuffling(混洗),將相同的單詞key放在一個桶里面,然后交給 reduce 處理。

第四步:reduce 接受到 shuffling 后的數(shù)據(jù), 會將相同的單詞進(jìn)行合并,得到每個單詞的詞頻數(shù),最后將統(tǒng)計好的每個單詞的詞頻數(shù)作為輸出結(jié)果。

上述就是 MapReduce 的大致流程,前兩步可以看做 map 階段,后兩步可以看做 reduce 階段。 MapReduce 將 作業(yè)的整個運行過程分為兩個階段:Map 階段和Reduce 階段。

1、Map 階段

Map 階段是由一定數(shù)量的 Map Task 組成。這些 Map Task 可以同時運行,每個 Map Task又是由以下三個部分組成。
1)對輸入數(shù)據(jù)格式進(jìn)行解析的一個組件:InputFormat。因為不同的數(shù)據(jù)可能存儲的數(shù)據(jù)格式不一樣,這就需要有一個 InputFormat 組件來解析這些數(shù)據(jù)的存放格式。默認(rèn)情況下,它提供了一個 TextInputFormat 來解釋數(shù)據(jù)格式。TextInputFormat 就是我們前面提到的文本文件輸入格式,它會將文件的每一行解釋成(key,value),key代表每行偏移量,value代表每行數(shù)據(jù)內(nèi)容。 通常情況我們不需要自定義 InputFormat,因為 MapReduce 提供了很多種InputFormat的實現(xiàn),我們根據(jù)不同的數(shù)據(jù)格式,選擇不同的 InputFormat 來解釋就可以了。這一點我們后面會講到。

2)輸入數(shù)據(jù)處理:Mapper。這個 Mapper 是必須要實現(xiàn)的,因為根據(jù)不同的業(yè)務(wù)對數(shù)據(jù)有不同的處理。

3)數(shù)據(jù)分組:Partitioner。Mapper 數(shù)據(jù)處理之后輸出之前,輸出key會經(jīng)過 Partitioner 分組或者分桶選擇不同的reduce。默認(rèn)的情況下,Partitioner 會對 map 輸出的key進(jìn)行hash取模,比如有6個Reduce Task,它就是模(mod)6,如果key的hash值為0,就選擇第0個 Reduce Task,如果key的hash值為1,就選擇第一個 Reduce Task。這樣不同的 map 對相同單詞key,它的 hash 值取模是一樣的,所以會交給同一個 reduce 來處理。

2、Reduce 階段

Reduce 階段由一定數(shù)量的 Reduce Task 組成。這些 Reduce Task 可以同時運行,每個 Reduce Task又是由以下四個部分組成。

  1. 數(shù)據(jù)運程拷貝。Reduce Task 要運程拷貝每個 map 處理的結(jié)果,從每個 map 中讀取一部分結(jié)果。每個 Reduce Task 拷貝哪些數(shù)據(jù),是由上面 Partitioner 決定的。

  2. 數(shù)據(jù)按照key排序。Reduce Task 讀取完數(shù)據(jù)后,要按照key進(jìn)行排序。按照key排序后,相同的key被分到一組,交給同一個 Reduce Task 處理。

  3. 數(shù)據(jù)處理:Reducer。以WordCount為例,相同的單詞key分到一組,交個同一個Reducer處理,這樣就實現(xiàn)了對每個單詞的詞頻統(tǒng)計。

  4. 數(shù)據(jù)輸出格式:OutputFormat。Reducer 統(tǒng)計的結(jié)果,將按照 OutputFormat 格式輸出。默認(rèn)情況下的輸出格式為 TextOutputFormat,以WordCount為例,這里的key為單詞,value為詞頻數(shù)。

InputFormat、Mapper、Partitioner、Reducer和OutputFormat 都是用戶可以實現(xiàn)的。通常情況下,用戶只需要實現(xiàn) Mapper和Reducer,其他的使用默認(rèn)實現(xiàn)就可以了。

2.MapReduce 內(nèi)部邏輯

下面我們通過 MapReduce 的內(nèi)部邏輯,來分析 MapReduce的數(shù)據(jù)處理過程。我們以WordCount為例,來看一下mapreduce 內(nèi)部邏輯,如下圖所示。

image

MapReduce 內(nèi)部邏輯的大致流程主要由以下幾步完成。

1、首先將 HDFS 中的數(shù)據(jù)以 Split 方式作為 MapReduce 的輸入。前面我們提到,HDFS中的數(shù)據(jù)是以 block存儲,這里怎么又變成了以Split 作為輸入呢?其實 block 是 HDFS 中的術(shù)語,Split 是 MapReduce 中的術(shù)語。默認(rèn)的情況下,一個 Split 可以對應(yīng)一個 block,當(dāng)然也可以對應(yīng)多個block,它們之間的對應(yīng)關(guān)系是由 InputFormat 決定的。默認(rèn)情況下,使用的是 TextInputFormat,這時一個Split對應(yīng)一個block。 假設(shè)這里有4個block,也就是4個Split,分別為Split0、Split1、Split2和Split3。這時通過 InputFormat 來讀每個Split里面的數(shù)據(jù),它會把數(shù)據(jù)解析成一個個的(key,value),然后交給已經(jīng)編寫好的Mapper 函數(shù)來處理。

2、每個Mapper 將輸入(key,value)數(shù)據(jù)解析成一個個的單詞和詞頻,比如(a,1)、(b,1)和(c,1)等等。

3、Mapper解析出的數(shù)據(jù),比如(a,1),經(jīng)過 Partitioner之后,會知道該選擇哪個Reducer來處理。每個 map 階段后,數(shù)據(jù)會輸出到本地磁盤上。

4、在reduce階段,每個reduce要進(jìn)行 shuffle 讀取它所對應(yīng)的數(shù)據(jù)。當(dāng)所有數(shù)據(jù)讀取完之后,要經(jīng)過Sort全排序,排序之后再交給 Reducer 做統(tǒng)計處理。比如,第一個Reducer讀取了兩個的(a,1)鍵值對數(shù)據(jù),然后進(jìn)行統(tǒng)計得出結(jié)果(a,2)。

5、將 Reducer 的處理結(jié)果,以O(shè)utputFormat數(shù)據(jù)格式輸出到 HDFS 的各個文件路徑下。這里的OutputFormat默認(rèn)為TextOutputFormat,key為單詞,value為詞頻數(shù),key和value之間的分割符為"\tab"。 由上圖所示,(a 2)輸出到Part-0,(b 3)輸出到Part-1,(c 3)輸出到Part-2。

3.MapReduce的基本架構(gòu)

和HDFS一樣,MapReduce也是采用Master/Slave的架構(gòu),其架構(gòu)圖如下所示。

image

MapReduce包含四個組成部分,分別為Client、JobTracker、TaskTracker和Task,下面我們詳細(xì)介紹這四個組成部分。

1)Client 客戶端

每一個 Job 都會在用戶端通過 Client 類將應(yīng)用程序以及配置參數(shù) Configuration 打包成 JAR 文件存儲在 HDFS,并把路徑提交到 JobTracker 的 master 服務(wù),然后由 master 創(chuàng)建每一個 Task(即 MapTask 和 ReduceTask) 將它們分發(fā)到各個 TaskTracker 服務(wù)中去執(zhí)行。

2)JobTracker

JobTracke負(fù)責(zé)資源監(jiān)控和作業(yè)調(diào)度。JobTracker 監(jiān)控所有TaskTracker 與job的健康狀況,一旦發(fā)現(xiàn)失敗,就將相應(yīng)的任務(wù)轉(zhuǎn)移到其他節(jié)點;同時,JobTracker 會跟蹤任務(wù)的執(zhí)行進(jìn)度、資源使用量等信息,并將這些信息告訴任務(wù)調(diào)度器,而調(diào)度器會在資源出現(xiàn)空閑時,選擇合適的任務(wù)使用這些資源。在Hadoop 中,任務(wù)調(diào)度器是一個可插拔的模塊,用戶可以根據(jù)自己的需要設(shè)計相應(yīng)的調(diào)度器。

3)TaskTracker

TaskTracker 會周期性地通過Heartbeat 將本節(jié)點上資源的使用情況和任務(wù)的運行進(jìn)度匯報給JobTracker,同時接收J(rèn)obTracker 發(fā)送過來的命令并執(zhí)行相應(yīng)的操作(如啟動新任務(wù)、殺死任務(wù)等)。TaskTracker 使用“slot”等量劃分本節(jié)點上的資源量。“slot”代表計算資源(CPU、內(nèi)存等)。一個Task 獲取到一個slot 后才有機(jī)會運行,而Hadoop 調(diào)度器的作用就是將各個TaskTracker 上的空閑slot 分配給Task 使用。slot 分為Map slot 和Reduce slot 兩種,分別供Map Task 和Reduce Task 使用。TaskTracker 通過slot 數(shù)目(可配置參數(shù))限定Task 的并發(fā)度。

4)Task

Task 分為Map Task 和Reduce Task 兩種,均由TaskTracker 啟動。HDFS 以固定大小的block 為基本單位存儲數(shù)據(jù),而對于MapReduce 而言,其處理單位是split。split 是一個邏輯概念,它只包含一些元數(shù)據(jù)信息,比如數(shù)據(jù)起始位置、數(shù)據(jù)長度、數(shù)據(jù)所在節(jié)點等。它的劃分方法完全由用戶自己決定。但需要注意的是,split 的多少決定了Map Task 的數(shù)目,因為每個split 只會交給一個Map Task 處理。Split 和 Block的關(guān)系如下圖所示:

image.png

Map Task 執(zhí)行過程如下圖 所示:由該圖可知,Map Task 先將對應(yīng)的split 迭代解析成一個個key/value 對,依次調(diào)用用戶 自定義的map() 函數(shù)進(jìn)行處理,最終將臨時結(jié)果存放到本地磁盤上, 其中臨時數(shù)據(jù)被分成若干個partition,每個partition 將被一個Reduce Task 處理。

image

Reduce Task 執(zhí)行過程下圖所示。該過程分為三個階段:

①從遠(yuǎn)程節(jié)點上讀取Map Task 中間結(jié)果(稱為“Shuffle 階段”);

②按照key 對key/value 對進(jìn)行排序(稱為“Sort 階段”);

③依次讀取< key, value list>,調(diào)用用戶自定義的reduce() 函數(shù)處理,并將最終結(jié)果存到HDFS 上(稱為“Reduce 階段”)。

image

4.MapReduce的數(shù)據(jù)本地性

在介紹數(shù)據(jù)本地性之前,我們首先介紹網(wǎng)絡(luò)拓?fù)涞母拍睢T谝粋€ Hadoop 集群里面,通常我們把這些機(jī)器按照機(jī)架來組織,比如說每個機(jī)架一般有16-64個節(jié)點。每個機(jī)架通過 Switch 交換機(jī)來通信,不同的機(jī)架又通過總的Switch交換機(jī)來交互。其架構(gòu)圖如下所示。

image

在上圖的架構(gòu)中,我們標(biāo)注了A、B、C、D四個節(jié)點,其中A、B、C三個節(jié)點存儲了block1數(shù)據(jù)塊。我們假設(shè)節(jié)點A要讀取block1數(shù)據(jù)塊,那么它的最佳選擇就是讀取它本身存儲的block1,此時讀取的速度最快、效率最高。如果A本身的block1數(shù)據(jù)塊丟失或者損壞,它就會選擇讀取同一個Switch機(jī)架下的B節(jié)點上的block1,這是因為在同一個機(jī)架下面讀取數(shù)據(jù)相對較快,所以不會選擇跨機(jī)架讀取C節(jié)點上面的block1,因為跨機(jī)架讀取數(shù)據(jù)的效率最差。除非A、B中的block1都丟失或者損壞,才會選擇跨機(jī)架讀取C節(jié)點上面的block1。

數(shù)據(jù)本地性(data locality)

那到底什么是數(shù)據(jù)本地性呢?如果一個任務(wù)運行在它將處理的數(shù)據(jù)所在的節(jié)點,我們就稱該任務(wù)具有“數(shù)據(jù)本地性”。數(shù)據(jù)的本地性可避免跨節(jié)點或者機(jī)架進(jìn)行數(shù)據(jù)傳輸,提高運行效率。

數(shù)據(jù)本地性分為三個類別:

1、同節(jié)點(node-local)。

2、同機(jī)架(rack-local)。

3、跨機(jī)架(off-switch)。

為了深入理解數(shù)據(jù)本地性的三個類別,我們下面舉個示例,如下圖所示

image

從上圖可以看出一共有四個機(jī)架:R1、R2、R3和R4,每個機(jī)架上有三個節(jié)點,每個節(jié)點上面存儲有不同的數(shù)據(jù)塊。比如,R1機(jī)架下有三個節(jié)點:H1、H2和H3,H1節(jié)點上有b1和b8數(shù)據(jù)塊,H2節(jié)點上有b1和b2數(shù)據(jù)塊,H3節(jié)點上有b2和b3數(shù)據(jù)塊。從上圖可以看出,每個數(shù)據(jù)塊有3個備份,按照 HDFS 的備份機(jī)制將這3個數(shù)據(jù)塊存儲到不同的節(jié)點上。下面我們來看一下數(shù)據(jù)本地性的三種類別。

1、我們假設(shè)Task1需要處理b1,H1節(jié)點正好有空閑資源得到Task1,H1節(jié)點存儲有b1,這時Task1在本節(jié)點上直接讀取b1,效率最高。這種情況下數(shù)據(jù)本地性稱之為node-local。

2、我們假設(shè)Task2需要處理b2,H4節(jié)點正好有空閑資源得到Task2,b2不在H4節(jié)點上,那么Task2會找到存儲有b2且距離最近的H5節(jié)點,H4和H5處于同一個機(jī)架,這時Task2會讀取同機(jī)架節(jié)點上的b2。這種情況下數(shù)據(jù)本地性稱之為rack-local。

3、我們假設(shè)Task3需要處理b3,H7節(jié)點正好有空閑資源得到Task3,b3并不在H7節(jié)點上,也不在H7同機(jī)架的節(jié)點上,而是在R1和R2機(jī)架下面的節(jié)點上,這時Task3就需要跨機(jī)架讀取b3,效率非常低下。這種情況下數(shù)據(jù)本地性稱之為off-switch。

三、MapReduce框架的容錯性

1、JobTracker

很不幸,JobTracker 存在單點故障,一旦出現(xiàn)故障,整個集群就不可用。這個是1.0里面出現(xiàn)的問題,在2.0里面這個問題已經(jīng)得到了解決。 不過大家放心,即使在1.0中,MapReduce也不會經(jīng)常出現(xiàn)故障。它可能一年也就是出現(xiàn)幾次故障,出現(xiàn)故障之后,你重啟一下,再把作業(yè)重新提交就可以了,它不會像 HDFS 那樣出現(xiàn)數(shù)據(jù)的丟失。 因為 MapReduce 是一個計算框架,計算過程是可以重現(xiàn)的,即使某個服務(wù)掛掉了,你重啟一下服務(wù),然后把作業(yè)重新提交,也是不會影響你的業(yè)務(wù)的。

2、TaskTracker

TaskTracker 周期性的向 JobTracker 匯報心跳,如果一定的時間內(nèi)沒有匯報這個心跳,JobTracker 就認(rèn)為該TaskTracker 掛掉了,它就會把上面所有任務(wù)調(diào)度到其它TaskTracker(節(jié)點)上運行。這樣即使某個節(jié)點掛了,也不會影響整個集群的運行。

3、MapTask和ReduceTask

MapTask和ReduceTask 也可能運行掛掉。比如內(nèi)存超出了或者磁盤掛掉了,這個任務(wù)也就掛掉了。 這個時候 TaskTracker 就會把每個MapTask和ReduceTask的運行狀態(tài)回報給 JobTracker,JobTracker 一旦發(fā)現(xiàn)某個Task掛掉了,它就會通過調(diào)度器把該Task調(diào)度到其它節(jié)點上。這樣的話,即使任務(wù)掛掉了,也不會影響應(yīng)用程序的運行。

MapReduce的錯誤處理機(jī)制

  1. 硬件故障
    在 Hadoop Cluster 中,只有一個 JobTracker,因此,JobTracker 本身是存在單點故 障的。如何解決 JobTracker 的單點問題呢?我們可以采用主備部署方式,啟動 JobTracker 主節(jié)點的同時,啟動一個或多個 JobTracker 備用節(jié)點。當(dāng) JobTracker 主節(jié)點出現(xiàn)問題時, 通過某種選舉算法,從備用的 JobTracker 節(jié)點中重新選出一個主節(jié)點。 機(jī)器故障除了 JobTracker 錯誤就是 TaskTracker 錯誤。TaskTracker 故障相對較為常 見,MapReduce 通常是通過重新執(zhí)行任務(wù)來解決該故障。 在 Hadoop 集群中,正常情況下,TaskTracker 會不斷的與 JobTracker 通過心跳機(jī)制 進(jìn)行通信。如果某 TaskTracker 出現(xiàn)故障或者運行緩慢,它會停止或者很少向 JobTracker 發(fā)送心跳。如果一個 TaskTracker 在一定時間內(nèi)(默認(rèn)是 1 分鐘)沒有與 JobTracker 通信, 那么 JobTracker 會將此 TaskTracker 從等待任務(wù)調(diào)度的 TaskTracker 集合中移除。同時 JobTracker 會要求此 TaskTracker 上的任務(wù)立刻返回。 如果此 TaskTracker 任務(wù)仍然在 mapping 階段的 Map 任務(wù),那么 JobTracker 會要求其他的 TaskTracker 重新執(zhí)行所有原 本由故障 TaskTracker 執(zhí)行的 Map 任務(wù)。如果任務(wù)是在 Reduce 階段的 Reduce 任務(wù),那 么 JobTracker 會要求其他 TaskTracker 重新執(zhí)行故障 TaskTracker 未完成的 Reduce 任務(wù)。 比如:一個 TaskTracker 已經(jīng)完成被分配的三個 Reduce 任務(wù)中的兩個,因為 Reduce 任務(wù) 一旦完成就會將數(shù)據(jù)寫到 HDFS 上,所以只有第三個未完成的 Reduce 需要重新執(zhí)行。但 是對于 Map 任務(wù)來說,即使 TaskTracker 完成了部分 Map,Reduce 仍可能無法獲取此節(jié) 點上所有 Map 的所有輸出。所以無論 Map 任務(wù)完成與否,故障 TaskTracker 上的 Map 任 務(wù)都必須重新執(zhí)行。
  2. 任務(wù)執(zhí)行失敗引發(fā)的故障
    在實際任務(wù)中,MapReduce 作業(yè)還會遇到用戶代碼缺陷或進(jìn)程崩潰引起的任務(wù)失敗等 情況。用戶代碼缺陷會導(dǎo)致它在執(zhí)行過程中拋出異常。此時,任務(wù) JVM 進(jìn)程會自動退出,并 向 TaskTracker 父進(jìn)程發(fā)送錯誤消息,同時錯誤消息也會寫入 log 文件,最后 TaskTracker 將此次任務(wù)嘗試標(biāo)記失敗。對于進(jìn)程崩潰引起的任務(wù)失敗,TaskTracker 的監(jiān)聽程序會發(fā)現(xiàn) 進(jìn)程退出,此時 TaskTracker 也會將此次任務(wù)嘗試標(biāo)記為失敗。對于死循環(huán)程序或執(zhí)行時間 太長的程序,由于 TaskTracker 沒有接收到進(jìn)度更新,它也會將此次任務(wù)嘗試標(biāo)記為失敗, 并殺死程序?qū)?yīng)的進(jìn)程。 在以上情況中,TaskTracker 將任務(wù)嘗試標(biāo)記為失敗之后會將 TaskTracker 自身的任務(wù) 計數(shù)器減 1,以便想 JobTracker 申請新的任務(wù)。TaskTracker 也會通過心跳機(jī)制告訴 JobTracker 本地的一個任務(wù)嘗試失敗。JobTracker 接到任務(wù)失敗的通知后,通過重置任務(wù) 狀態(tài),將其加入到調(diào)度隊列來重新分配該任務(wù)執(zhí)行(JobTracker 會嘗試避免將失敗的任務(wù) 再次分配給運行失敗的 TaskTracker)。如果此任務(wù)嘗試了 4 次(次數(shù)可以進(jìn)行設(shè)置)仍沒 有完成,就不會再被重試,此時整個作業(yè)也就失敗了。

四、MapReduce資源組織方式

MapReduce 計算框架并沒有直接調(diào)用 CPU和內(nèi)存等多維度資源,它把多維度資源抽象為 “slot”,用 “slot” 來描述資源的數(shù)量。管理員可以在每個節(jié)點上單獨配置slot個數(shù)。slot可以分為map slot和reduce slot。從一定程度上,slot可以看做“任務(wù)運行并行度”。如果某個節(jié)點配置了5個map slot,那么這個節(jié)點最多運行5個Map Task;如果某個節(jié)點配置了3個reduce slot,那么該節(jié)點最多運行3個Reduce Task。下面我們分別介紹 Map slot和Reduce slot。

1、Map slot

1)Map slot 可用于運行 Map Task 的資源,而且只能運行 Map Task。

2)每個 Map Task 通常使用一個map slot。而比如像容量調(diào)度器,它可以有比較大的 MapTask。這樣的MapTask使用內(nèi)存比較多,那么它可能使用多個map slot。

2、Reduce slot

1)Reduce slot 可用于運行ReduceTask,而且只能運行ReduceTask。

2)每個ReduceTask通常使用一個reduce slot。而比如像容量調(diào)度器,它可以有比較大的 ReduceTask。這樣的ReduceTask使用內(nèi)存比較多,那么它可能使用多個reduce slot。

五、MapReduce的數(shù)據(jù)傾斜優(yōu)化

數(shù)據(jù)分布:正常的數(shù)據(jù)分布理論上都是傾斜的,就是我們所說的20-80原理:80%的財富集中在20%的人手中, 80%的用戶只使用20%的功能 , 20%的用戶貢獻(xiàn)了80%的訪問量 。
產(chǎn)生原因:
Mapreduce程序在運行的時候,運行了大部分,但是還有部分reduce還在運行,甚至長時間運行,最終導(dǎo)致整個程序運行時間很長才結(jié)束。
造成這種現(xiàn)象的主要原因是:
reduce程序處理的key的條數(shù)比其他key的條數(shù)大很多,這也就造成了分配到數(shù)據(jù)巨大的key的節(jié)點長時間運行。本質(zhì)講數(shù)據(jù)傾斜就是數(shù)據(jù)分布不均。出現(xiàn)場景:
不同的數(shù)據(jù)字段可能的數(shù)據(jù)傾斜一般有兩種情況:
一種是唯一值非常少,極少數(shù)值有非常多的記錄值(唯一值少于幾千)
一種是唯一值比較多,這個字段的某些值有遠(yuǎn)遠(yuǎn)多于其他值的記錄數(shù),但是它的占比也小于百分之一或千分之一
解決方案:
方式1:增加reduce 的jvm內(nèi)存
既然reduce 本身的計算需要以合適的內(nèi)存作為支持,在硬件環(huán)境容許的情況下,增加reduce 的內(nèi)存大小顯然有改善數(shù)據(jù)傾斜的可能,這種方式尤其適合數(shù)據(jù)分布第一種情況,單個值有大量記錄, 這種值的所有紀(jì)錄已經(jīng)超過了分配給reduce 的內(nèi)存,無論你怎么樣分區(qū)這種情況都不會改變。
方式2: 增加reduce 個數(shù)
這個對于數(shù)據(jù)分布第二種情況有效,唯一值較多,單個唯一值的記錄數(shù)不會超過分配給reduce 的內(nèi)存. 如果發(fā)生了偶爾的數(shù)據(jù)傾斜情況,增加reduce 個數(shù)可以緩解偶然情況下的某些reduce 不小心分配了多個較多記錄數(shù)的情況. 但是對于第一種數(shù)據(jù)分布無效。
方式3: 自定義partition
如果map輸出鍵的單詞來源于一本書。其中大部分必然是省略詞(stopword: a,the,or )。那么就可以將自定義分區(qū)將這部分省略詞發(fā)送給固定的一部分reduce實例。而將其他的都發(fā)送給剩余的reduce實例。
方式4:設(shè)定combiner
減少流向reduce的文件數(shù)量,從而減輕reduce數(shù)據(jù)傾斜。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容