hadoop實踐總結

jiaaq2008發表於2014-04-03

參考:http://wind-bell.javaeye.com/blog/81490  《hadoop入門轉》設法找原文作者url沒有找到。

         http://hi.baidu.com/atlahla/blog/item/4e8e37039f64a48dd43f7cfe.html 《在Linux下設定最簡單的ssh安全自動登入》

概論
    作為Hadoop程式設計師,他要做的事情就是:
    1、定義Mapper,處理輸入的Key-Value對,輸出中間結果。
    2、定義Reducer,可選,對中間結果進行規約,輸出最終結果。
    3、定義InputFormat 和OutputFormat,可選,InputFormat將每行輸入檔案的內容轉換為Java類供Mapper函式使用,不定義時預設為String。
    4、定義main函式,在裡面定義一個Job並執行它。
   

    然後的事情就交給系統了。
    1.基本概念:Hadoop的HDFS實現了google的GFS檔案系統,NameNode作為檔案系統的負責排程執行在master,DataNode執行在每個機器上。同時Hadoop實現了Google的MapReduce,JobTracker作為MapReduce的總排程執行在master,TaskTracker則執行在每個機器上執行Task。

    2.main()函式,建立JobConf,定義Mapper,Reducer,Input/OutputFormat 和輸入輸出檔案目錄,最後把Job提交給JobTracker,等待Job結束。

    3.JobTracker,建立一個InputFormat的例項,呼叫它的getSplits()方法,把輸入目錄的檔案拆分成FileSplist作為Mapper task 的輸入,生成Mapper task加入Queue。

    4.TaskTracker 向 JobTracker索求下一個Map/Reduce。
      
     Mapper Task先從InputFormat建立RecordReader,迴圈讀入FileSplits的內容生成Key與Value,傳給Mapper函式,處理完後中間結果寫成SequenceFile.
     Reducer Task 從執行Mapper的TaskTracker的Jetty上使用http協議獲取所需的中間內容(33%),Sort/Merge後(66%),執行Reducer函式,最後按照OutputFormat寫入結果目錄。

      TaskTracker 每10秒向JobTracker報告一次執行情況,每完成一個Task10秒後,就會向JobTracker索求下一個Task。

      Nutch專案的全部資料處理都構建在Hadoop之上,詳見Scalable Computing with Hadoop。


    二、程式設計師編寫的程式碼
    我們做一個簡單的分散式的Grep,簡單對輸入檔案進行逐行的正則匹配,如果符合就將該行列印到輸出檔案。因為是簡單的全部輸出,所以我們只要寫Mapper函式,不用寫Reducer函式,也不用定義Input/Output Format。

package  demo.hadoop

public   class  HadoopGrep {

  public   static   class  RegMapper  extends  MapReduceBase  implements  Mapper {

   private  Pattern pattern;

   public   void  configure(JobConf job) {
   pattern  =  Pattern.compile(job.get( " mapred.mapper.regex " ));
  }

   public   void  map(WritableComparable key, Writable value, OutputCollector output, Reporter reporter)
     throws  IOException {
   String text  =  ((Text) value).toString();
   Matcher matcher  =  pattern.matcher(text);
    if  (matcher.find()) {
    output.collect(key, value);
   }
  }
 }

  private  HadoopGrep () {
 }  //  singleton

  public   static   void  main(String[] args)  throws  Exception {
  
  JobConf grepJob  =   new  JobConf(HadoopGrep. class );
  grepJob.setJobName( " grep-search " );
  grepJob.set( " mapred.mapper.regex " , args[ 2 ]);

  grepJob.setInputPath( new  Path(args[ 0 ]));
  grepJob.setOutputPath( new  Path(args[ 1 ]));
  grepJob.setMapperClass(RegMapper. class );
  grepJob.setReducerClass(IdentityReducer. class );
      
  JobClient.runJob(grepJob);
 }
}

        RegMapper類的configure()函式接受由main函式傳入的查詢字串,map() 函式進行正則匹配,key是行數,value是檔案行的內容,符合的檔案行放入中間結果。
        main()函式定義由命令列引數傳入的輸入輸出目錄和匹配字串,Mapper函式為RegMapper類,Reduce函式是什麼都不做,直接把中間結果輸出到最終結果的的IdentityReducer類,執行Job。

        整個程式碼非常簡單,絲毫沒有分散式程式設計的任何細節。

三.執行Hadoop程式
3.1實踐前準備:
 3.1.1.下載hadoop程式  使用者製作的程式
 3.1.2.兩臺機器: 
           a.主控機器server 192.168.0.52

           b.客戶機client  192.168.0.53

3.2.非叢集方式:
      把hadoop程式 使用者製作的程式 上傳到linux機器上 使hadoop/bin目錄下的指令碼具有可執行許可權
      完全不進行任何分散式計算,不動用任何namenode,datanode的做法,適合一開始做除錯程式碼。
       解壓hadoop,其中conf目錄是配置目錄,hadoop的配置檔案在hadoop-default.xml,如果要修改配置,不是直接修改該檔案,而是修改hadoop-site.xml,將該屬性在hadoop-site.xml裡重新賦值。
       hadoop-default.xml的預設配置已經是local執行,不用任何修改,配置目錄裡唯一必須修改的是hadoop-env.sh 裡JAVA_HOME的位置。
       將編譯好的HadoopGrep與RegMapper.class 放入hadoop/build/classes/demo/hadoop/目錄 找一個比較大的log檔案放入一個目錄,然後執行
       hadoop / bin / hadoop demo.hadoop.HadoopGrep log檔案所在目錄 任意的輸出目錄 grep的字串

     檢視輸出目錄的結果,檢視hadoop/logs/裡的執行日誌。  
     在重新執行前,先刪掉輸出目錄。

3.3.單機叢集:
  第1步.    然後修改hadoop-site.xml ,加入如下內容:
< property > 
   < name > fs.default.name </ name > 
   < value > server:9000 </ value >   //指定名位元組點服務
</ property > 
< property > 
   < name > mapred.job.tracker </ name > 
   < value > server:9001 </ value > //指定合併節點服務
</ property > 
< property > 
   < name > dfs.replication </ name > 
   < value > 1 </ value > 
</ property >

    從此就將執行從local檔案系統轉向了hadoop的hdfs系統,mapreduce的jobtracker也從local的程式內操作變成了分散式的任務系統,9000,9001兩個埠號是隨便選擇的兩個空餘埠號。  
  另外,如果你的/tmp目錄不夠大,可能還要修改hadoop.tmp.dir屬性。
第2步. 增加ssh不輸入密碼即可登陸。
A為本地主機(即用於控制其他主機的機器) ;
B為遠端主機(即被控制的機器Server), 假如ip為192.168.60.110;
A和B的系統都是Linux

在A上執行命令:
# ssh-keygen -t rsa (連續三次回車,即在本地生成了公鑰和私鑰,不設定密碼)
# ssh root@192.168.60.110 "mkdir .ssh" (需要輸入密碼)
# scp ~/.ssh/id_rsa.pub root@192.168.60.110:.ssh/id_rsa.pub (需要輸入密碼)  //用這種方法實現把公匙複製被控制機器上

在B上的命令:
# touch /root/.ssh/authorized_keys (如果已經存在這個檔案, 跳過這條)
# cat /root/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys (將id_rsa.pub的內容追加到authorized_keys 中)

回到A機器:
# ssh -i 私鈅路徑 root@192.168.60.110 (不需要密碼, 登入成功)     //-i 引數指定本地金鑰,如果私匙在.ssh中,且名稱為id_rsa,則不用i指定密匙位置
經典舉例:,

首先 ssh-keygen -t rsa 命令生成了一個金鑰和一個公鑰, 而且金鑰可以設定自己的密碼

可以把金鑰理解成一把鑰匙, 公鑰理解成這把鑰匙對應的鎖頭,

把鎖頭(公鑰)放到想要控制的server上, 鎖住server, 只有擁有鑰匙(金鑰)的人, 才能開啟鎖頭, 進入server並控制

而對於擁有這把鑰匙的人, 必需得知道鑰匙本身的密碼,才能使用這把鑰匙 (除非這把鑰匙沒設定密碼), 這樣就可以防止鑰匙被了配了(私鑰被人複製)   [比較經典]
    
上面是一個通用規則:

  本機執行只需要把id_rsa.pub追加到authorized_keys中即可
這樣使用ssh root@server即可以不用輸入密碼登入

  3.格式化namenode,執行
  bin/hadoop namenode -format

  4.啟動Hadoop
     執行hadoop/bin/start-all.sh, 在本機啟動namenode,datanode,jobtracker,tasktracker
  
  5.現在將待查詢的log檔案放入hdfs,。   //很重要 否則下一步會報找不到檔案路徑錯誤
     執行hadoop/bin/hadoop dfs 可以看到它所支援的檔案操作指令。
     執行hadoop/bin/hadoop dfs put log檔案所在目錄 in ,則log檔案目錄已放入hdfs的/user/user-name/in 目錄中

  6.現在來執行Grep操作
      hadoop/bin/hadoop demo.hadoop.HadoopGrep in out
      檢視hadoop/logs/裡的執行日誌,重新執行前。執行hadoop/bin/hadoop dfs rmr out 刪除out目錄。
  7.把hdfs中的目的檔案取到本地:
    執行hadoop/bin/hadoop dfs -get out 本地路徑
  8.執行hadoop/bin/stop-all.sh 結束

3.4.多機叢集:
 
  進行3.3的所有配置後,在執行以下步驟
  第一步:  把hadoop 和應用程式 以及配置檔案 完全拷貝到要加入成為節點伺服器的client機器  第二步: 修改server機器上的slaves(中文奴隸的意思)檔案,這個檔案中一行表示一個節點 把client  ip地址加入
          例如:
               localhost 或server或192.168.0.52
               client 或192.168.0.53
  第三步: 按照3.3中所講的方法實現從server不用輸入密碼登入到client機器
   方法是:在server機器上執行命令

            scp /root/.ssh/id_rsa.pu root@client:.ssh
            讓輸入登入到clint密碼,輸入即可
          然後登入到client機器執行命令:
           cp /root/.ssh/id_rsa.pub /root/.ssh/authorized_keys
     即可
 第四步:在hadoop-server執行hadoop/bin/start-all.sh
   將會在hadoop-server啟動namenode,datanode,jobtracker,tasktracker
   在hadoop-server2啟動datanode 和tasktracker
  
 第五步.現在來執行Grep操作
     hadoop/bin/hadoop demo.hadoop.HadoopGrep in out
    重新執行前,執行hadoop/bin/hadoop dfs rmr out 刪除out目錄

 第六步.執行hadoop/bin/stop-all.sh 結束
              
提示:新加入一個臺節點伺服器,只需要執行第1.2.3步即可

相關文章