Hadoop Distributed Cache 共享archives時的問題(以MapFile的共享爲例)

在Hadoop分佈式處理中,如果需要在map和reduce任務中共享一些只讀的數據,可以將這些數據配置在配置信息中(JobConf)。但是,根據《Hadoop權威指南》中所述,如果各計算結點間需要共享的只讀數據量較大,由於配置信息的大小受到各計算結點的內存大小的限制,因此最好是採用Distributed Cache。可以在Job啓動前,利用如下代碼在Distributed Cache中添加文件或是存檔:


DistributedCache.addCacheFile(new URI("/myapp/data.data"), jobconf); //添加文件
DistributedCache.addCacheArchive(new URI("/myapp/archive.zip"), jobconf); //如果是要共享一個目錄,先將其打包成.zip, .tar.gz等的壓縮文件


在Mapper或是Reducer中可以利用如下代碼獲得所共享的文件或是存檔信息:

 public static class MapClass extends MapReduceBase  
     implements Mapper<K, V, K, V> {
     
       private Path[] localArchives;
       private Path[] localFiles;
       
       public void configure(JobConf job) {
         // Get the cached archives/files
         localArchives = DistributedCache.getLocalCacheArchives(job); //獲得共享的文檔的本地路徑列表,同時DistributedCache機制爲將存檔自動解壓,
                                                                                                                       //因此所獲得的路徑是一個目錄

         localFiles = DistributedCache.getLocalCacheFiles(job);   //獲得共享的文件的本地路徑列表
       }
       
       public void map(K key, V value, 
                       OutputCollector<K, V> output, Reporter reporter) 
       throws IOException {
         // Use data from the cached archives/files here
         // ...
         // ...
         output.collect(k, v);
       }
     }


但是,在利用DistributedCache共享archives時,所獲得的路徑並不完全是原來的壓縮文件解壓後得到的目錄,其中還含有其他內容,因此在操作時需要注意。

以下以共享MapFile爲例,MapFile顧名思義就是一種磁盤版的Map結構,便於根據Key值進行快速查找,在磁盤上MapFile以一個目錄的形式存放

圖中P爲最上層的目錄,其下存在一個MapFile文件爲part-00000,它包括data和index文件。

現在在MapReduce時將P加入DistributedCache中,首先將P壓縮成zip文件,

在Job啓動前的代碼中加入如下語句:

DistributedCache.addCacheArchive(new URI(args[4]), conf);  //其中args[4]是P.zip文件文件在路徑名,一般都要先將它放到HDFS中

然後在Mapper或是Reducer代碼添加如下代碼獲得MapFile的Readers



public static class MapClass extends MapReduceBase 
           implements Mapper<K, V, K, V> 
{ 
     private MapFile.Reader[] readers = null; 
     private Path P_PATH;
     private Path[] localArchives; 
     private String p_path_name; 
     public void configure(JobConf conf) { 
          p_path_name = conf.get("P_path_name"); 
          try{
              localArchives = DistributedCache.getLocalCacheArchives(conf);}
          catch(IOException e){
                    System.out.println("get cache files error");
          }
          System.out.println("num of LocalArchives is " + localArchives.length);
          if(localArchives.length > 0 ) {
                P_PATH = localArchives[0];
          } 
          Path path = this.P_PATH;
          try{ 
               File zipDir = new File(path.toString());
               String[] zipFiles = zipDir.list();
               String mapfileDir = null;
               for(int i = 0; i < zipFiles.length; ++i)
               {
                   if(zipFiles[i].equals(this.p_path_name))
                   {
                      mapfileDir = "file://" + path.toString() + "/" + zipFiles[i]; //查找真正存放mapfiles的目錄,加上"file://"表示是在本地文件系統, DistributedCache會將共享的目錄和文件放到本地文件系統上
                    }
                    System.out.println("zipFiles[i] is " + zipFiles[i]);
                }
               System.out.println("mapfileDir is " + mapfileDir);
               Path mapFilePath = new Path(mapfileDir);
               FileSystem newFs = mapFilePath.getFileSystem(conf);
               System.out.println("mapfile path is " + mapFilePath.toString());
               this.readers = MapFileOutputFormat.getReaders(newFs, mapFilePath, conf); //獲得MapFile readers,在一個目錄下存在多個mapFile可以一次獲取多個readers
         }catch(IOException e) {
            System.out.println("fail to create mapfile readers");
        }
}



在本例中利用DistributedCache.getLocalCacheArchives(conf)獲得的路徑名爲....../P.zip,但它是一個目錄,其下存在

P.zip ------文件,原始的zip文件

P ------目錄,zip解壓得到,要找的就是這個目錄

             其中包括part-00000,這是真正的 mapfile

.P.zip.crc ------zip壓縮時的校驗文件

因此在獲得P.zip路徑後,還需要進一步查找,在能確定最終解壓後的目錄所在,這是利用DistributedCache共享archives時需要注意的問題。






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章