Hive中Map任務和Reduce任務數量計算原理

Hive中Map任務和Reduce任務數計算原理

MapReduce原理

  • Map階段(以FileInputFormat爲例)
    步驟:map, partition, sort, combiner

    • InputFormat負責計算分片,一個分片對應一個Map任務,InputFormat而且還負責創建RecordReader,通過RecordReadernext()方法,然後循環調用map()方法
    • map()方法的輸入爲一行文本,處理的結果先是寫到內存緩衝區,達到閾值之後,溢寫到磁盤,如果多次溢出,則會有多個溢出文件,這些溢出文件經過了分區,排序,而且還可能作過Combiner,map任務結束之後,多個溢出文件會合併成一個,結果寫在本地
  • Reduce階段
    步驟:copy, sort, reduce

    • reduce階段先會進行copy,如果copy過來的文件很小,則直接copy到內存中,如果文件較大,則copy到磁盤
    • copy完成之後,會進行一個歸併,由於在map端已經作過排序,所以,歸併其實是在將多個有序的文件合併成一個有序的文件,這個文件中,一個key會生成一條記錄,value爲這個key對應的數組
    • 對歸併後的文件循環調用reduce()方法,對每個key進行處理。

Map數量

hive的Map數量與分片大數量一致,一個分片生成一個Map任務,分片不是數據本身,是記錄了數據的位置和長度,長度用於考慮優先運行,位置用於查找數據,一個分片大小的計算取決於使用的InputFormat(具體使用哪個Inputformat可以在執行計劃中查看到),不同的InputFormat計算分片的邏輯可能有所不同。

Hadoop程序中,對於FileInputformat,分片的計算方式爲:

  • 分片大小splitSize=Math.max(minSize, Math.min(goalSize, blockSize));
  • long goalSize = totalSize / (numSplits == 0 ? 1 : numSplits);,totalSize爲輸入文件的總大小,numSplits爲用戶配置的map數量(mapreduce.job.maps)
  • minSize,用戶配置的最小分片大小
  • blockSize,文件塊大小,默認128M

如果小文件太多,默認情況下會生成太多的map,這樣很影響效率,所以,對於CombineFileInputFormat,根據節點和機架的因素,會把多個小文件合併成一個分片,生成更少的map數

配置解釋:

  • mapreduce.input.fileinputformat.split.maxsize,分片的最大size,默認256000000,即256Mb
  • mapreduce.input.fileinputformat.split.minsize.per.node,最小分片大小,單位byte,默認大小1,如果想配置成256Mb,則爲256 * 1000 * 1000,需要注意配置???
  • mapreduce.input.fileinputformat.split.minsize.per.rack
  • mapreduce.job.maps,每個jobe的map任務數量,默認2

Map任務數量調整策略

影響Map數量的因素:文件大小,文件數量,塊大小,配置的Map數量,`InputFormat`類
- 調大Map數量
  - 調小`mapreduce.input.fileinputformat.split.maxsize`(`mapred.max.split.size`已過時),當值小於`blockSize`時纔有效

- 調小Map數量
  - 調大`mapreduce.input.fileinputformat.split.minsize.per.node`和`mapreduce.input.fileinputformat.split.minsize.per.rack`,當這二者的值大於blockSize纔有效,此時最好配合使用`mapreduce.job.max.split.locations`(表示分片最大的location,默認大小爲10,表示一個map處理的split的文件不能超過10個節點),如果超過10,則可能會導致數據錯誤

Reduce數量

Reduce任務的數量,首先是取用戶設置的配置reduce數量,如果在沒有指定數量的時候,是由程序自動估算出來的,具體情況如下:

1、Map Join的時候,沒有reduce數量
2、如果有配置mapreduce.job.reduces,則使用這個值作爲reduce數量
3、如果沒有配置mapreduce.job.reduces,則進行reduce估算過程,具體的估算過程如下

  • 獲取bytesPerReducer,由hive.exec.reducers.bytes.per.reducer配置,默認256Mb
  • 獲取maxReducers,由hive.exec.reducers.max配置,默認1009
  • 計算samplePercentage
  • 計算totalInputFileSize,總的輸入文件的大小
  • 計算powersOfTwo,如果使用bucket,並且hive.exec.infer.bucket.sort.num.buckets.power.two=true時才生效,默認這個值爲false
    再根據以下判斷邏輯計算出最終的估算的reduce數量:
	double bytes = Math.max(totalInputFileSize, bytesPerReducer);
    int reducers = (int) Math.ceil(bytes / bytesPerReducer);
    reducers = Math.max(1, reducers);
    reducers = Math.min(maxReducers, reducers);

因此,從公式中可以得出,影響reduce數量的因素包括:輸入總大小,每個reduce處理的數據量
reduce的數量與分區沒有關係,但最終生成的文件數量與分區有關係,在沒有合併reduce的輸出的情況下,reduce生成的文件數量等於分區數量或reduce數量

配置解釋:

  • hive.exec.reducers.bytes.per.reducer,每個reduce處理的size,默認256Mb
  • mapreduce.job.reduces,reduce數量,默認爲1
  • hive.exec.reducers.max,reduce任務的最大數量,默認1009

reduce數量調整策略

  • 調大reduce數量
    • 調大mapreduce.job.reduces,但是要注意,如果這個值太多,會生成多餘的空文件,會浪費reduce資源,比如,分區只有20,但這個reduce數量調成30,則會申請30個reduce, 但實際只有20個有用。
    • 調小hive.exec.reducers.bytes.per.reducer,但注意不要調太小,否則容易生成太多小文件

注意:調大reduce的數量,並不等價於提高了併發度,有可能只是多起了reduce的個數,但依然像之前那樣傾斜

  • 調小reduce數量
    • 調小mapreduce.job.reduces,可能會影響並行度
    • 調大hive.exec.reducers.bytes.per.reducer,但會增加每個reduce的壓力
    • 調小hive.exec.reducers.max
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章