2010-06-10 75 views
2

我正在開發應用程序以使用Hadoop框架處理(和合並)幾個大型Java序列化對象(大小爲GB)。 Hadoop商店在不同的主機上分發文件的塊。但是,由於反序列化需要所有的塊都存在於單個主機上,所以它會大幅度地提升性能。與文本文件不同,我怎樣才能處理這種情況:不同的塊必須不能單獨處理?Hadoop:處理大型序列化對象

回答

3

有兩個問題:一個是每個文件都必須(在初始階段)被整個處理:看到第一個字節的映射器必須處理該文件的所有其餘部分。另一個問題是局部性:爲了獲得最佳效率,你希望每個這樣的文件的所有塊都駐留在同一個主機上。在整個


處理文件:

一個簡單的竅門是讓第一階段的映射過程的文件名,而不是其內容的列表。如果您想要運行50個地圖作業,請使用這部分文件名製作50個文件。這很容易,可以與java或流式傳輸hadoop一起使用。

或者,使用不可拆分的輸入格式,例如NonSplitableTextInputFormat

有關更多詳細信息,請參閱hadoop wiki上的「How do I process files, one per map?」和「How do I get each of my maps to work on one complete input-file?」。


地點:

這留下一個問題,但是,你正在閱讀的塊都跨HDFS disributed:通常是性能增益,這裏真正的問題。我不相信有任何方法可以將特定的塊連接在HDFS中。

是否可以將文件放置在每個節點的本地存儲中?這實際上是解決這個問題的最高性能和最簡單的方法:讓每臺機器啓動作業以處理例如文件中的所有文件。 /data/1/**/*.data(與你關心的高效使用本地分區和CPU核心數一樣聰明)。

如果這些文件來自SAN或來自說s3,那就試試直接從那裏拉出來:它的目的是爲了處理羣體。


使用第一招的說明:如果某些文件是比別人大的多,把他們獨自在最早命名的上市,以避免投機性執行力的問題。無論如何,如果任務可靠並且您不希望某些批次處理多次,則可以關閉此類作業的投機執行。

2

我認爲基本的(無益的)答案是你不能真正做到這一點,因爲它直接違背了MapReduce範例。映射器和減速器的輸入和輸出單位是相對較小的記錄。 Hadoop在這些方面運行,而不是磁盤上的文件塊。

你確定你的進程需要一臺主機上的所有東西嗎?任何我想描述爲合併的東西都可以像MapReduce那樣相當乾淨地實現,並且沒有這樣的要求。

如果您希望確保某些鍵(及其值)最終位於同一個縮減器上,則可以使用Partitioner來定義鍵映射到reducer實例的方式。根據你的情況,這可能是你真正的追求。

我也會說你聽起來像是在試圖對HDFS文件進行操作,而不是編寫Hadoop MapReduce。所以也許你的問題真的是關於如何在HDFS上打開幾個SequenceFile s,手動讀取它們的記錄併合並。這並不是一個Hadoop問題,但是,仍然不需要在一臺主機上安裝塊。

+0

讓我來重述一下我的問題。因此,通常在輸入文件中能夠被Mapper函數(如在文本文件中)進行部分讀取和處理。就我而言,我打算使用2個Mapper函數,第一個將二進制文件分成較小的(鍵,值)對,第二個用於更傳統的Mapper目的。我的問題是我能做些什麼來處理二進制文件(比如說圖像,序列化對象),這將需要所有的塊在同一主機上,然後才能開始處理。希望能解釋我的問題。我感謝你的迴應。 – restrictedinfinity 2010-06-10 08:47:38

+1

我不認爲這需要所有塊在一臺主機上。它確實要求工作人員從HDFS傳輸足夠的塊以讀取至少一個完整的記錄。但無論如何,數據必須最終到達工作人員。我想說讓HDFS來處理它。 – 2010-06-10 10:58:24

3

聽起來你的輸入文件是一個大的序列化對象。是這樣嗎?你可以用一個簡單的鍵使每個項目具有自己的序列化值嗎?例如,如果您想要使用Hadoop並行調整圖像大小,您可以逐個序列化每個圖像並使用簡單的索引鍵。您的輸入文件將是一個文本文件,其中鍵值對是索引鍵,然後序列化的blob將是該值。

在Hadoop中進行模擬時,我使用這種方法。我的序列化的blob是模擬所需的所有數據,關鍵僅僅是表示模擬編號的整數。這使我可以像Grid Engine一樣使用Hadoop(特別是Amazon Elastic Map Reduce)。