1. 程式人生 > >Hadoop中split數量和reader讀取原則

Hadoop中split數量和reader讀取原則

畫一個簡單的hadoop執行圖

這裡我以單詞計數為例,在WCapp(在上篇博文《split數量計演算法則》有原始碼)中設定最小切片數值和最大切片數值,把最大切片數值設定成13,即13個位元組

 

要計數的資料

 

 

這裡有個問題我們把切片值的設的很小,第一個切片讀到的內容:hello world t,那麼一個切片裝不了一行,資料被切斷,那麼reader是怎麼讀的呢?

我們這裡還是在jobsubmitter類中的writeSplits中打斷點Debug執行程式

step over 到  maps = this.writeNewSplits(job, jobSubmitDir);這一行,然後step into進入

再進入到input.getSplits(job)中

 

我們可以看到minSize=1,maxSize = 13,這是我們剛才設定最大切塊大小的值。(至於這些方法怎麼得到這些值的在上一篇文章有講過)

下面就是一大堆原始碼,判斷是否能切成split(一些壓縮是不能切),這些就不說了,有興趣的自己試驗研究。

直接在方法底打斷點

 

可以看到切片數量有四個,我們有三行資料,每行資料量都大於切片值,有四個切片也說的通。在確定每個切片的內容

可以看見有0~3共四個切片,第一個切片行偏移量為0,有13個位元組,其他的也以此類推,只有最後一個切片只有10個位元組的資料。

一個切片對應一個map任務,那麼第一個切片他的map任務切到資料應該是 hello world t

那麼我們直接就在自己寫的WCmapper中打一個斷點,程式執行到這裡檢視value中的值是否是hello world t

我們可以看到讀到值是完整的一行,而不是hello world t

這才合理嘛。如何是按切片值來讀,那麼很大可以讀取到不完整的資料,我們計算的結果也會是錯誤的。

這裡有個很重要的類Recordreader,也就是最上面圖上,inputformat到map中間有一個reader,你切片可以這樣定義,但是reader要去讀資料,他會首先判斷讀取的位置是不是行首,若是,則會一直讀到回車換行;若不是行首,它會從下一行開始讀。這就是為什麼我們第二個切片內容會是一個完整的行內容,而不是從第一行的 om 開始讀。

所以我們雖然有四個切片,但是我們只有前三個split有資料,最後一個split是空的,因為我們只有三行資料,依照reader的讀取資料法則,到最後一個split的時候我們已近沒有資料可讀了。

這裡我們可能會問,split和reader這到底聽誰的?或者他們倆的功能感覺差不多?

  假設split的大小是128M,我們讀了n行資料,在第n行讀了一半,如果不讀剩下的,會丟資料,這裡可能會說,下一個切片把資料讀走再分析,但是在併發情況下,切片很大可能在不同節點上執行的,怎麼把這兩個資料對接在一起再分析。所以這時候就需要reader了,就算我們split值滿了,我們還是要把這行讀完。(reader是一行一行的把資料發給mapper的)

切片是定義大方向的,而這個reader是處理細節,讓你不丟失資料,或者資料不錯亂。