2011-02-10 186 views
2

我有一個要求,我的映射器可能在某些情況下爲另一個映射器處理產生新的鍵/值。有沒有一個理智的方式來做到這一點?我想過編寫自己的自定義輸入格式(隊列?)來實現這一點。有任何想法嗎?謝謝!Hadoop遞歸映射

編輯:我要澄清

方法1

 
Map Step 1 
(foo1, bar1) -> out1 
(foo2, bar2) -> out2 
(foo3, bar3) -> (fooA, barA), (fooB, barB) 
(foo4, bar4) -> (fooC, barC) 

Reduction Step 1: 
(out1) -> ok 
(out2) -> ok 
((fooA, barA), (fooB, barB)) -> create Map Step 2 
((fooC, barC)) -> also send this to Map Step 2 

Map Step 2: 
(fooA, barA) -> out3 
(fooB, barB) -> (fooD, barD) 
(fooC, barC) -> out4 

Reduction Step 2: 
(out3) -> ok 
((fooD, barD)) -> create Map Step 3 
(out4) -> ok 

Map Step 3: 
(fooD, barD) -> out5 

Reduction Step 3: 
(out5) -> ok 

-- no more map steps. finished -- 

所以這是完全遞歸。一些鍵/值會減少輸出,一些會生成新的映射鍵/值。我真的不知道在給定的運行中我可能會遇到多少個Map或Reduce步驟。

方法2

 
Map Step 1 
(foo1, bar1) -> out1 
(foo2, bar2) -> out2 
(foo3, bar3) -> (fooA, barA), (fooB, barB) 
(foo4, bar4) -> (fooC, barC) 
(fooA, barA) -> out3 
(fooB, barB) -> (fooD, barD) 
(fooC, barC) -> out4 
(fooD, barD) -> out5 

Reduction Step 1: 
(out1) -> ok 
(out2) -> ok 
(out3) -> ok 
(out4) -> ok 
(out5) -> ok 

這種方法會得到映射給它自己的輸入列表中。我不確定最終實施哪種方式會更簡單。

+0

我的理解是否正確,不同的輸入具有不同深度的MR處理?一個MR處理一個,而另一個需要一個鏈? – 2011-02-10 16:24:45

+0

是的,完全正確。一個很好的比喻是遞歸目錄列表。該映射器將採取一個目錄,並將發射文件。如果我打到另一個目錄,我會將它反饋給映射器。 – eric 2011-02-10 17:33:53

+0

等一下,我認爲這是另一種方式。我的意思是說,它將類似於一個接收文件併發布它們的映射器。如果其中一個文件碰巧是一個目錄,它將讀取目錄的內容,並將每個文件反饋到映射器中。 – eric 2011-02-10 18:44:11

回答

1

通過Hadoop進行遞歸的「方法1」方法迫使您通過Map和Reduce爲每個「遞歸深度」運行完整數據集。這意味着你必須確定這可能會有多深,並且你會受到巨大的性能影響。

你能肯定地說遞歸深度是有限的嗎?

如果是這樣,那麼我肯定會去「方法2」,並實際上建立映射器,以便在一個映射器調用中執行所需的遞歸。 它更簡單,併爲您節省大量的性能。

1

使用oozie [網格工作流定義語言]將兩個M/R作業與只有映射器的第一個作業串聯在一起。 http://yahoo.github.com/oozie

+0

我可能應該提到我使用Amazon Elastic MapReduce。他們不支持oozie :(但它看起來像一個非常有趣的框架,我沒有足夠的瞭解文檔,看看我是否真的能夠獲得遞歸行爲,但我會保持它在雷達上。 – eric 2011-02-11 20:36:16

1

根據我的理解,Hadoop MR框架在作業開始時就規劃了哪些地圖任務應該執行,並且尚未準備好讓新的地圖任務動態顯示。
我會建議兩種可能的解決方案: a)如果您在映射階段發出另一對 - 將它們饋送到同一個映射器。因此,mapper將採用其通常的參數,並且在處理之後會查看某些內部本地隊列以供其他對處理。如果有少量的輔助對,那麼它會工作得很好,而數據局部性並不重要。
b)如果你確實在處理目錄或類似的東西 - 你可以遍歷作業包主體中的結構,並構建你需要的所有分割。