2012-11-21 51 views
2

您好,我目前正在學習Map Reduce,並試圖用hadoop 1.0.4構建一個小的Job。我有一個stopp單詞列表和一個模式列表。在我的文件映射之前,我想在一個有效的數據結構(如地圖)中加載stoppwords。我也想從我的模式列表中構建一個正則表達式模式。由於這些是串行任務,我希望在映射前執行​​它們,並將每個映射器的副本傳遞給它們可以讀取/寫入的對象。我想在我的驅動程序類中使用帶有getter的靜態變量,但是使用java調用對象作爲指針原理,這種方法無法解決。在我通過它之前,我當然可以克隆這個對象,但這看起來並不是一個好習慣。我讀了一些關於分佈式緩存的內容,但據我瞭解,它只適用於文件而不適用於對象,並且我可以讓每個映射器都讀取停止詞/模式文件。將對象副本傳遞給hadoop中所有映射器的最佳實踐

感謝您的幫助!

回答

2

可能的解決方案是在運行作業012xx之前將stopwords.txt複製到HDFS,然後在Mapper的setup方法中將其讀入適當的數據結構中。 E.g:

MyMapper類:

... 
private Map<String, Object> stopwords = null; 

@Override 
public void setup(Context context) { 
    Configuration conf = context.getConfiguration(); 
    //hardcoded or set it in the jobrunner class and retrieve via this key 
    String location = conf.get("job.stopwords.path"); 
    if (location != null) { 
     BufferedReader br = null; 
     try { 
      FileSystem fs = FileSystem.get(conf); 
      Path path = new Path(location); 
      if (fs.exists(path)) { 
       stopwords = new HashMap<String, Object>(); 
       FSDataInputStream fis = fs.open(path); 
       br = new BufferedReader(new InputStreamReader(fis)); 
       String line = null; 
       while ((line = br.readLine()) != null && line.trim().length() > 0) { 
        stopwords.put(line, null); 
       } 
      } 
     } 
     catch (IOException e) { 
      //handle 
     } 
     finally { 
      IOUtils.closeQuietly(br); 
     } 
    } 
} 
... 

然後你可以使用禁用詞地圖中的方法。

另一個選擇是用jobrunner類中的停用詞創建地圖對象, 將其序列化爲Base64編碼的字符串,將其作爲Configuration對象中的某個鍵的值傳遞給映射器,並在設置中將其反序列化方法。

我會選擇第一個選項,不僅僅因爲它更簡單,而且因爲通過Configuration對象傳遞更多數據不是一個好主意。

+0

我是否正確理解該設置僅被調用一次?因爲那正是我需要的。 – benehsv

+0

是的。在每個map/reduce任務中,會發生以下情況:對於每個輸入記錄,調用一次setup(),然後調用map()/ reduce(),最後清理() –

+0

而不是使用停用詞的Map並執行stopwords.put(line ,null),你可以使用HashSet並做stopwords.add(line)。 – Naijaba

2

Hadoop分佈式緩存是特定於將某些引用數據傳遞給映射器的機制。從性能的角度來看,最好從HDFS加載 - 因爲每個節點數據將從HDFS傳遞到本地文件系統,而不是每個任務一次。
你完全正確 - 它只適用於文件和閱讀文件並將它們轉換爲你的數據結構是你的責任。
根據我的理解,hadoop不支持傳遞對象。雖然如果你將在這些文件中使用某種序列化,它將接近你所要求的。

相關問題