2013-05-26 42 views
3

這是我想要做的。現在我有一些文本文件是這樣的:Hadoop:我如何爲每個值賦予一個全球唯一的ID號碼作爲Mapper中的關鍵字?

<page> 
<url>xxx.example.com</url> 
<title>xxx</title> 
<content>abcdef</content> 
</page> 

<page> 
<url>yyy.example.com</url> 
<title>yyy</title> 
<content>abcdef</content> 
</page> 

... 

我想讀的映射文件分割,並將其轉換爲鍵值對,其中每個值是一個<page>標籤的內容。

我的問題是關於關鍵。我可以使用網址作爲鍵,因爲它們是全球唯一的。但是,由於我的工作環境,我想要生成一個全球唯一編號作爲每個鍵值對的關鍵字。我知道這與Hadoop的水平可伸縮性有某些關係。但是有沒有解決辦法?

+0

@ThomasJungblut每個任務的塊ID應該是更好的選擇,因爲作業可以容忍散列中的少數衝突。在爲每個映射器任務分配ID塊之後應該做什麼? – Denzel

+0

我會先將task_id和計算的ID偏移量放到配置中,以便每個任務都可以獲取它的起始ID,然後開始遞增。您需要事先知道映射器的數量,以及大塊中有多少條記錄,這不是不可能解決的,但卻很笨拙。 –

+0

@ThomasJungblut是的。解決這個問題很笨拙。如果我使用諸如時間(毫秒)之類的東西來保持密鑰的唯一性,該怎麼辦?與網址哈希相比,它可以減少衝突嗎? – Denzel

回答

1

如果你要處理這些文件由MapReduce的我會採取以下策略:

  1. 使用一般的文本輸入格式,一行行。這會導致每個不同的文件都轉到不同的映射器工作。
  2. 在映射器構建週期中,讀取循環中的下一行,通過context.nextKeyValue()而不是每行調用。
  3. 饋線一些語法分析器(也許你只是夠看了6個非空行,也許你會使用類似libxml,但最後你會代對象的數量。
  4. 如果您打算傳遞對象你讀給減速器您需要將其包裝成的東西,實現Writable interaface
  5. 要形成鑰匙我會用UUID實施java.util.UUID喜歡的東西:

    UUID鍵= UUID.randomUUID();

    這就夠了如果你每秒沒有創造數十億記錄,而你的工作不需要100年。 :-)

  6. 只需要注意 - UUID應該可能編碼在ImmutableBytesWritable類中,對於這樣的事情很有用。

  7. 就是這樣,context.write(object,key)

好吧,你的reducer(如果有的話)和輸出格式是另一回事。如果您在映射期間沒有將它們轉換爲Text之類的東西,則您肯定需要輸出格式來存儲對象。

+0

UUID應該是一個很好的解決方案。但與URLHash相比,它的優勢是什麼? – Denzel

+1

如果您使用高質量的隨機生成器,UUID真的很獨特。 http://en.wikipedia.org/wiki/Universally_unique_identifier#Random_UUID_probability_of_duplicates –

+0

順便說一句,即使你使用足夠好的散列URL和一些毫秒時間戳,因爲你以最快的速度處理URL,無論如何你都有很高的重複概率。 –

0

不知道這是否直接回答你的問題。但我正在利用輸入文件格式。

您可以使用NLineInputFormat並設定N = 6爲每條記錄包括6號線:

<page> 
<url>xxx.example.com</url> 
<title>xxx</title> 
<content>abcdef</content> 
</page> 
. 

與每個記錄,映射器將獲得的文件中的偏移位置。這個偏移對每個記錄都是唯一的。

PS:只有在架構固定的情況下它纔有效。我很懷疑它是否能夠正確處理多個輸入文本文件。

+0

這是一個很好的嘗試。但正如你所考慮的,我的輸入模式並不固定。內容可能由幾行組成...... – Denzel

相關問題