2010-06-25 40 views
5

我在Hadoop 0.20中有一份工作,需要一次處理大文件。 (這是一個預處理步驟,可以將面向文件的數據轉換爲更適合MapReduce的清潔的基於行的格式。)使用零縮減器時,可以從Hadoop獲得單獨排序的映射器輸出嗎?

我不介意我有多少個輸出文件,但每個Map的輸出都可以在最多隻有一個輸出文件,並且每個輸出文件都必須進行排序。

  • 如果我使用numReducers = 0運行,它會很快運行,並且每個映射器都會寫出自己的輸出文件,這很好 - 但文件沒有排序。
  • 如果我添加一個Reducer(簡單的Reducer.class),那麼會爲單個文件添加一個不必要的全局排序步驟,這需要花費很多個小時(比Map任務要長得多)。
  • 如果我添加多個縮減器,各個地圖作業的結果會混合在一起,因此一個Map的輸出會以多個文件結束。

有沒有什麼辦法說服Hadoop對每個作業的輸出執行映射端排序,而無需使用Reducers或其他任何方式來跳過緩慢的全局合併?

回答

2

做全局排序的一種方法是有一個自定義分區程序,併爲您的reducer做範圍分區。爲了這個工作,你必須知道你的mapper輸出鍵的範圍。您可以將您的密鑰範圍分成n個桶,其中n是減速器的數量。根據密鑰映射到的存儲區,映射器輸出會被路由到特定的還原器。各減速機的

輸出進行排序。由於範圍分區,所有減速器輸出的集合被全局排序。你所要做的就是按照與文件名中的5位數相同的順序來取得Reducer輸出文件。

有一點需要注意的是在你的密鑰分配的扭曲,這將導致集羣中的不均勻減速負載。如果您有分配信息,即密鑰的直方圖,則可以緩解此問題。然後你可以讓你的水桶長度不相等,並且每一個都擁有大致相同數量的鑰匙。

希望它有幫助。

0

請參閱本下面的評論 - 這是行不通的。我會在這裏留下這個錯誤的答案,這樣我們至少知道什麼是行不通的。

我相信這就是Combiner會爲你做的。我從來沒有使用過自己,但http://hadoop.apache.org/common/docs/r0.20.1/mapred_tutorial.html狀態(部分負載/映射器):

用戶可以選擇指定一個 組合器,經由 JobConf.setCombinerClass(類),以 執行 中間輸出的本地聚合,這有助於 減少從映射器傳輸到 減速器的數據量 。

我對此的看法是,如果您將身份縮減器指定爲組合器,則應對每個映射器的輸出進行排序。

+0

我確實有「job.setCombinerClass(Reducer.class)」。當減速器爲零時似乎不起作用。 From Mapper.java:

如果作業有零減少,那麼Mapper的輸出直接寫入OutputFormat而不用按鍵排序。

所以我想我詢問是否有規避這一點,或其它方式獲取相同的效果的一種方式。 – 2010-06-25 13:01:37

+0

太糟糕了。 因此,有可能在映射的'map'叫你不輸出任何東西,只是藏在內存中收集的值(使用足夠的映射器,以確保這不會受到太大)。然後在'cleanup'調用中自己排序這些值然後輸出它們。 – 2010-06-25 13:16:20

+0

是的 - 我想我會自己排序它,雖然每個映射器的內存可能是一個問題...感謝您的輸入。 – 2010-06-25 13:42:15

2

組合器不會對數據進行全局排序 - 它們基本上是一個緩存來部分聚合reducer數據。

通常情況下,您不想單獨對每個映射器的輸出進行排序,但是如果這樣做,爲什麼不將映射器文件ID添加爲輸出的一部分,並使用自定義分區函數,以便將每個映射器的輸出單獨分區,並因此單獨排序,因此任何映射器的輸出總是在單個文件中?您也可能想要按文件ID進行分組,以便分別獲得每個輸入文件的排序輸出。

我很好奇,爲什麼要分開排序mapper輸出呢?

另一個想法是,如果您對輸出進行排序,Hadoop實際上會對映射端進行排序(「shuffle」),所以如果您使用多個reducer運行,您可能不會刪除這些臨時文件。

+0

這聽起來像它可能是一個部分解決方案 - 與許多減速器運行速度,但忽略其輸出,而不是保留臨時排序的映射文件。 我想映射器輸出文件作爲未來作業的輸入,一直希望保持排序,因爲它們具有按時間順序排列的結構,使排序後的文件更易於使用。 但是我現在要走的路線是使用不同的mapper輸出格式,在沒有嚴格排序時更容易查詢 - 感覺像MR更適合MR。 感謝您的回答。 – 2010-06-25 17:21:33

1

如果你的映射器所消耗的數據不顯著大,你才能避免它收集和跟蹤數據在本地,排序的數據結構。然後,您可以在清理/定稿步驟中編寫/收集已排序的數據。

相關問題