2013-10-16 57 views
1

假設我有這樣的信息的大TSV文件:什麼決定減速器的數量以及如何避免減速器的瓶頸?

2012-09-22 00:00:01.0 249342258346881024 47268866 0 0 0 bo 
2012-09-22 00:00:02.0 249342260934746115 1344951  0 0 4 ot 
2012-09-22 00:00:02.0 249342261098336257 346095334 1 0 0 ot 
2012-09-22 00:05:02.0 249342261500977152 254785340 0 1 0 ot 

我想要實現列舉了五分鐘的時間間隔MapReduce工作和過濾的TSV輸入一些信息。輸出文件應該是這樣的:

0 47268866 bo 
0 134495 ot 
0 346095334 ot 
1 254785340 ot 

的關鍵是間隔的數量,例如,0是2012-09-22 00:04:592012-09-22 00:00:00.0之間的間隔的參考。

我不知道這個問題是否適合MapReduce方法,或者我沒有正確地思考。在map函數中,我只是將時間戳作爲關鍵字並將過濾後的信息作爲值傳遞。在reduce函數中,我通過使用全局變量來計算時間間隔,並生成所提到的輸出。

i。框架是否自動確定某些reducer的數量還是用戶自定義的?用一個reducer,我認爲我的方法沒有問題,但是我想知道在處理真正大的文件時,一個reduce是否會成爲瓶頸,是嗎?

ii。如何用多個減速器解決這個問題?

任何建議將非常感激! 在此先感謝!

編輯:

的第一個問題是@Olaf回答,但第二次還是給了我關於並行有些疑惑。我的地圖功能的地圖輸出是目前這個(我只是路過微小精確時間戳):

2012-09-22 00:00 47268866 bo 
2012-09-22 00:00 344951  ot 
2012-09-22 00:00 346095334 ot 
2012-09-22 00:05 254785340 ot 

所以在減少功能我收到的鍵表示分鐘收集信息時,輸入和值的信息本身,我想枚舉從0開始的五分鐘間隔。我目前正在使用一個全局變量來存儲間隔的開始,當一個關鍵外推它我增加了間隔計數器(這也是一個全局變量)。

下面是代碼:

private long stepRange = TimeUnit.MINUTES.toMillis(5); 
private long stepInitialMillis = 0; 
private int stepCounter = 0; 

@Override 
public void reduce(Text key, Iterable<Text> values, Context context) 
     throws IOException, InterruptedException { 

    long millis = Long.valueOf(key.toString()); 
    if (stepInitialMillis == 0) { 
     stepInitialMillis = millis; 
    } else { 
     if (millis - stepInitialMillis > stepRange) { 
      stepCounter = stepCounter + 1; 
      stepInitialMillis = millis; 
     } 
    } 
    for (Text value : values) { 
     context.write(new Text(String.valueOf(stepCounter)), 
       new Text(key.toString() + "\t" + value)); 
    } 
} 

因此,與多個減速,我將我減少對兩個或多個節點功能運行,在兩個或兩個以上的JVM,我將失去在全球提供的控制變量和我沒有考慮我的情況的解決方法。

回答

2

減速器的數量取決於集羣的配置,儘管您可以限制MapReduce作業使用的減速器的數量。

如果您正在處理大量數據,那麼單個reducer實際上會成爲MapReduce作業的瓶頸。

Hadoop MapReduce引擎保證所有與同一個鍵相關的值都發送到同一個reducer,因此您的方法應該可以與multile reducer配合使用。查看Yahoo!教程細節:http://developer.yahoo.com/hadoop/tutorial/module4.html#listreducing

編輯:爲了保證在相同的時間間隔的所有值去同一個減速,你將不得不使用的時間間隔爲重點的一些獨特的標識符。你將不得不在映射器中執行它。我再次閱讀你的問題,除非你想以某種方式聚合相同時間間隔內的記錄之間的數據,否則根本不需要任何減速器。

編輯:正如@SeanOwen指出的,減速器的數量取決於集羣的配置。通常它被配置爲每個節點的最大任務數乘以數據節點數的0.95到1.75倍。如果未在集羣配置中設置mapred.reduce.tasks值,則還原器的默認數量爲1.

+0

謝謝你的快速回答!關於第二個問題,我編輯了我的帖子,以更好地解釋我的問題。 –

+1

@JoãoMelo:我再次重新閱讀您的問題並編輯我的答案。您想要的功能最好在映射器中實現。 – Olaf

+0

我同意你的看法,但在我的方法中,間隔計數器從文件的第一個時間戳開始,在這種情況下是第一個塊的第一個時間戳。我想這是不可能的,因爲每個節點將運行一個實例,使用不同的塊和不同的全局變量,對嗎? –

1

看起來您希望將某些數據按五分鐘塊聚合。使用Hadoop進行Map-Reduce對於這種事情非常有用!應該沒有理由使用任何「全局變量」。以下是我如何設置:

映射器讀取TSV的一行。它抓住時間戳,並計算它屬於哪個5分鐘桶。將其作爲一個字符串,並將其作爲鍵發出,如「20120922:0000」,「20120922:0005」,「20120922:0010」等。至於與該鍵一起發出的值,只需保持簡單就可以開始,並將整個製表符分隔的行作爲另一個Text對象發送。

既然映射器已經確定瞭如何組織數據,那麼減速器的工作就是完成聚合。每個減速器將獲得一把鑰匙(五分鐘之一的一個釦環),以及適合該桶的所有線的列表。它可以遍歷該列表,並從中提取所需的任何內容,並根據需要將輸出寫入上下文。

至於映射器,只是讓hadoop指出這一部分。作爲起點,將減速器的數量設置爲集羣中有多少個節點。應該運行得很好。

希望這會有所幫助。