2013-10-29 103 views
1

我試圖使用Hadoop來格式化和排序非常大的數據集,但它似乎在跳過排序步驟。該映射器將Avro輸入文件轉換爲JSON中的一些有趣的字段。什麼會導致Hadoop跳過排序步驟?

void map(AvroWrapper<Datum> wrappedAvroDatum, NullWritable nothing, 
     OutputCollector<Text, Text> collector, Reporter reporter) { 
    Datum datum = wrappedAvroDatum.datum(); 
    if (interesting(datum)) { 
     Long time = changeTimeZone(datum.getTime()); 
     String key = "%02d".format(month(time)); 
     String value = "{\"time\": %d, \"other-stuff\": %s, ...}".format(time, datum.getOtherStuff()); 
     collector.collect(new Text(key), new Text(value)); 
    } 
} 

減速器假定每個鍵的值是字典順序(適用於org.apache.hadoop.io.Text,對吧?),只是去掉了按鍵,使我得到一個文本文件,每行一個JSON對象。

void reduce(Text key, java.util.Iterator<Text> values, 
      OutputCollector<NullWritable, Text> collector, Reporter reporter) { 
    while (values.hasNext()) { 
     collector.collect(NullWritable.get, new Text(values.next())); 
    } 
} 

我期待的是在一個月塊排序文本文件(也就是,我並不指望幾個月是爲了,但我希望每一個月內的時間是按順序)。我得到的是按月份分組但卻完全未排序的文本文件。顯然,Hadoop將Text記錄按其鍵值分組,但不會對它們進行排序。

(已知問題:我依靠的事實是"time"在我的JSON對象中排在第一位,並且所有記錄的位數都完全相同,所以詞典順序是數字順序。 )

當我使用Hadoop Streaming(不是該項目中的選項)時,文本行被自動排序---排序可以配置,但默認情況下它做了我想要的。在原始Hadoop中,排序是否需要以某種方式打開?如果是這樣,怎麼樣?如果它應該默認打開,我可以從哪裏開始調試這個問題?

我正在觀察Cloudera的CDH4 Hadoop-0.20軟件包在僞分佈式模式和Amazon Elastic Map-Reduce(EMR)中的這種行爲。

回答

2

Hadoop對鍵進行排序,而不是數值。這意味着你得到的結果是正確的。 Hadoop沒有跳過排序階段;它實際上是對鍵進行排序。

您可以設計自己的Writable類型以使用組合鍵並確保您想要的排序類型。這其他SO question解釋如何做到這一點。

最後,this other SO question給出了有關在Hadoop中排序階段如何工作的更多信息。

+0

認真?!?在過去的一兩年Hadoop使用中,我不知何故錯過了這個基本觀點。我將不得不回過頭去看看Hadoop Streaming是否因做了一些不同的事情而誤導了我,或者我真的很無心以至於沒有注意到這一點。儘管如此,我將密鑰更改爲「%15d」.format(time)',現在我可以得到完全有序的結果,無需逐月塊(一個不錯的獎勵)。 –

+0

我懷疑,當你使用流媒體時,你使用文本行作爲鍵,這就是爲什麼他們被排序。你可以看到[這個流教程](http://www.michael-noll.com/tutorials/writing-an-hadoop-mapreduce-program-in-python/)並檢查排序步驟是否與'sort - k1,1',即對鍵進行排序(按值排序將是'sort -k2,2')。 – cabad

+0

@ jim-pivarski另請參閱我剛添加的最後一段。它鏈接到另一個SO問題,更多關於洗牌和排序階段的細節。 – cabad