2015-09-07 87 views
0

我正在使用Map Reduce框架。MapReduce:將Reducer的結果分組爲固定大小的塊

比方說,這是輸入列表[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P ,Q, R, S, T, U, V, W, X, Y, Z] 和我的映射器產生以下輸出:

<"Key 1" : A> 
<"Key 2" : B> 
<"Key 3" : C> 
<"Key 1" : D> 
<"Key 2" : E> 
<"Key 3" : F> 
<"Key 1" : G> 
<"Key 2" : H> 
<"Key 3" : I> 
<"Key 1" : J> 
<"Key 2" : K> 
<"Key 3" : L> 
<"Key 1" : M> 
<"Key 2" : N> 
<"Key 3" : O> 
<"Key 1" : P> 
<"Key 2" : Q> 
<"Key 3" : R> 
<"Key 1" : S> 
<"Key 2" : T> 
<"Key 3" : U> 
<"Key 1" : V> 
<"Key 2" : W> 
<"Key 3" : X> 
<"Key 1" : Y> 
<"Key 2" : Z> 

現減速機的輸出通常是這樣的:

<"Key 1" : A, D, G, J, M, P, S, V, Y> 
<"Key 2" : B, E, H, K, N, Q, T, W, Z> 
<"Key 3" : C, F, I, L, O, R, U, X> 

但我想要什麼要做的事情是這樣的:

我想把每個鍵的輸出分成3塊,然後產生t他最終減速器輸出。

所以我想我的減速機的輸出看起來是這樣的:

<"Key 1" : [A, D, G], [J, M, P], [S, V, Y]> 
<"Key 2" : [B, E, H], [K, N, Q], [T, W, Z]> 
<"Key 3" : [C, F, I], [L, O, R], [U, X]> 

任何幫助,將不勝感激由於兩個日以來,我被困在這個問題上。我無法弄清楚最後一部分,即如何將輸出分成3塊。

P.S.如果塊大小小於3(例如最後一個鍵的例子),那麼它很好,但不應該超過3.

+0

不知道,你是什麼意思的3塊是什麼意思?您已經獲得了減速器中每個鍵的數據,您可以隨意輸出。這個塊將成爲一個ArrayList,或者你只需​​要用'[]'格式化輸出' – gyan

+0

@gyan有一個底層應用程序,讓我們假設它發送一條消息給用戶,批量大小爲3,將消耗Reducer的輸出。 現在Reducer的結果存儲在某個文件中,底層應用程序從文件中選擇一個輸出並對其進行處理。 舉個例子: 應用程序一次只能處理3個ID,所以我們直接提供3個塊的輸出。所以當應用程序選擇一個輸出時,它可以直接處理它。 –

+0

好吧,所以如果我理解正確..你需要輸出像線1 - Key1:A,D,G; 2號線 - Key1:J,M,P。即使數據屬於同一個密鑰,它應該在每行3個塊中最大。如果是這樣,請在查詢中添加正確的格式。 – gyan

回答

1

我認爲,這是簡單的事:

  1. 在你減速機,只需要3個值每次向一個for循環。
  2. 串聯這三個與您所選擇的分隔符和寫入方面

    context.write(鍵,值)

請注意,你可以寫上下文儘可能多的時間,你希望,即 爲3個輸出的每個塊簡單地寫入上下文,然後取下一組 的3個值。

請讓我知道,如果你發現任何困難。

更復雜的解決方案可以使用MultiOutputs。你甚至可以用這個寫入不同的文件。

一個很好的例子是here使用Hadoop 1.0.2

下面是從的javadoc採取的例子:

Usage in Reducer: 

<K, V> String generateFileName(K k, V v) { 
    return k.toString() + "_" + v.toString(); 
} 

public class MOReduce extends 
    Reducer<WritableComparable, Writable,WritableComparable, Writable> { 
private MultipleOutputs mos; 
public void setup(Context context) { 
... 
mos = new MultipleOutputs(context); 
} 

public void reduce(WritableComparable key, Iterator<Writable> values, 
Context context) 
throws IOException { 
... 
mos.write("text", , key, new Text("Hello")); 
mos.write("seq", LongWritable(1), new Text("Bye"), "seq_a"); 
mos.write("seq", LongWritable(2), key, new Text("Chau"), "seq_b"); 
mos.write(key, new Text("value"), generateFileName(key, new Text("value"))); 
... 
} 

public void cleanup(Context) throws IOException { 
mos.close(); 
... 
} 

} 
+0

非常感謝! :)'for'循環解決方案爲我工作完美!從來沒有想過解決方案會變成這個簡單! 不知道我們可以多次寫入'context'。也謝謝你! :) 沒有嘗試其他的方法,所以不能告訴它的正確性。 –

+0

但在上下文中多次寫入時,寫入上下文是一個沉重的權重過程,並有可能觸發羣集內的推測性執行。在複雜情況下,MultiOutputs是優化的解決方案。 – gyan

0

是的,你可以使用ArrayWritable作爲固定大小塊在你的情況減速機價值班。

你可以做的是,

  • 在 減速機類保持與固定大小的3實例數組列表變量。

  • 在您的reduce()中,迭代給定鍵的值列表 並將其添加到數組列表中。

  • 如果數組列表的大小達到3,則只需將其轉換爲
    ArrayWritable實例,並把它傳遞給寫入()與鍵,然後復位 數組列表。

  • 在您的作業
    config中聲明異常值類爲ArrayWritable。

+0

感謝您的解決方案,但由@gyan給出的解決方案爲我工作!使用'for'循環爲我工作。 –

+0

很酷,很高興聽到...請不要忘記打勾@ gyan的答案的最佳答案/ upvote .. – sureshsiva