Hadoop的僞分佈式與分佈式環境配置

Hadoop

【親自測試沒問題 於是分享給初學者】  

1、Hadoop簡介

1、hadoop的誕生

Nutch和Lucene之父Doug Cutting在2006年完成Hadoop項目。

Hadoop並不是一個單詞,它來源於DougCutting小兒子對所玩的小象玩具牙牙學語的稱呼。就像是google也是由小孩子命名一樣。

後又經過5年的開發,hadoop在所有云計算系統是穩居第一。

Hadoop目前使用最廣泛的版本爲hadoop-0.20版本。目前最新版本爲hadoop-1.03

Hadoop運行在Linux系統中。在windows上安裝可使用cgywin模擬linux環境。

2、hadoop的組成

hadoop Common – 是hadoop的核心,包括文件系統、遠程調用RPC的序列化函數。

HDFS : 提供高吞吐量的可靠分佈式文件系統是 GFS的開源實現。

Hadoop的文件系統。必須通過hadoop  fs 命令來讀取。支持分佈式。

MapReduce : 大型分佈式數據處理模型,是Google MapReduce的開源實現。

合併/計算模型。

其他相關組成:

•    Hbase:結構化分部式數據庫。BigTable的開源實現。

•    Hive:提供摘要和查詢功能的數據倉庫。

•    Cassandra:由Facebook開發分佈式數據倉庫。目前已經捐獻給apache。且apache已經將Cassandra應用到了各種雲計算系統中。

3、hadoop的體系結構

   NameNode  - 主節點主服務器

   SecondaryNameNode– 是輔助nameNode

   DataNode  -數據保存用的

   TackTracker – 接收任務

       JobTracker  - 分數據 -100M  Datanode1,DataNode2,DataNode3

      

l  NameNode:這是hadoop的守護進程(注意是進程JVM)。負責記錄文件是如何分割成數據塊,以及這些數據塊分別存儲到哪些數據節點上。對內存進行集中管理。NameNode在整個hadoop中只有一個。一旦NameNode服務器宕機,整個系統將無法運行。

l  DataNode:集羣中的每個從服務器都運行一個DataNode後臺程序。這個後臺程序負責將HDFS數據塊寫到本地的文件系統。

l  Secondary NomeNode:用來監控HDFS狀態的輔助後臺程序。如保存NameNode的快照。

l  JobTracker:用戶連接應用程序和hadoop。每一個hadoop集羣中只一個 JobTracker,一般它運行在Master節點上。

l  TaskTracker:負責與DataNode進行結合。

4、Hadoop的市場

l  facebook

l  淘寶

l  360完全

l  京東

l  yahoo

l  google

l  暴風

 

2、Hadoop的安裝

Core-site.xml:

       官方只提供linux的安裝版本:

      

       目前市場上出現了一種window上的可以安裝的版本。其實是將Linux與hadoop整合的產物。目的是簡化hadoop的安裝。此安裝程序使用的是hadoop-0.20版本+cgywin:

      

      

1、hadoop的單機安裝-hadoop4win的安裝方法

       Hadoop的使用包括

n  安裝

n  格式化NameNode

n  啓動所有節點

 

       Hadoop4win的安裝方法非常簡單,因爲它就是一個setup安裝程序,只要會點下一步即可。

      

選擇語言:

接收:

選擇組件:

選擇安裝位置:

等待安裝:

查看hadoop的安裝細節:

安裝細節:

安裝細節:格式化namenode:

安裝細節-測試啓動所有節點:

注意下面的停止順序:

 

Hadoop安裝完成以後的目錄:

hadoop4win是Linux+jdk+hadoop的安裝目錄。

Var是namenode格式化以後生成的目錄 。即hdfs的目錄。

 

 

 

 

 

 

 

進入hadoop4win:

查看hadoop的配置文件:

Hadoop-env.sh:hadoop的環境變量配置文件

 

Core-site.xml:hadoop的核心配置文件

 

Hdfs-site.xml:hadoop的文件系統配置文件

 

Mapred-site.xml:hadoop的map/reduce配置文件。

 

 

查看上面文件的配置信息,你對了解hadoop有幫助。

 

2、啓動hadoop

1、直接使用hadoop的start-haoop

2、使用jsp檢查java進程

       如果發現有5個java進程,則說明啓動成功:

或使用ps命令:

3、單個啓動與停止hadoop

       啓動和停止hadoop必須要遵循節點的順序。

       啓動時按以下順序啓動:(停止時按相反的順序停止)

       Namenode

       Datanode

       Secondarynamenode

       Jobtracker

       Tasktracker

      

       使用hadoop-daemon.sh start 啓動各節點:

      

檢查啓動是否成功:

      

停止:

       使用hadoop-daemon.sh stop namenode停止每個節點即可

 

3、測試訪問

       Hadoop啓動以後,訪問50030端口可以訪問jobtracker。

       訪問50070端口可以訪問hdfs文件系統。

       http://localhost:50030 - Jobtracker

       http://localhost:50070 - hdfs

以下是50070

 

3、hdfs概念與命令

       Hdfs是hadoop Distributed file system的縮寫,是hadoop的分佈式文件系統。

       Hdfs由hadoop來管理,它不同於普通的文件系統,不能直觀的查找文件,必須要通過hadoop命令操作hdfs。

 

       HDFS是一個主從結構的體系,一個HDFS集羣是由一個名字節點,它是一個管理文件的命名空間和調節客戶端訪問文件的主服務器,當然還有的數據節點,一個節點一個,它來管理存儲。HDFS暴露文件命名空間和允許用戶數據存儲成文件。

  內部機制是將一個文件分割成一個或多個的塊,這些塊存儲在一組數據節點中。名字節點操作文件命名空間的文件或目錄操作,如打開,關閉,重命名,等等。它同時確定塊與數據節點的映射。數據節點來負責來自文件系統客戶的讀寫請求。

  數據節點同時還要執行塊的創建,刪除,和來自名字節點的塊複製指示。

  名字節點和數據節點都是軟件運行在普通的機器之上,機器典型的都是linux,HDFS是用java來寫的,任何支持java的機器都可以運行名字節點或數據節點,利用java語言的超輕便型,很容易將HDFS部署到大範圍的機器上。典型的部署時將有一個專門的機器來運行名字節點軟件,機羣中的其他機器運行一個數據節點實例。體系結構排斥在一個機器上運行多個數據節點的實例,但是實際的部署不會有這種情況。

集羣中只有一個名字節點極大地簡單化了系統的體系。名字節點是仲裁者和所有HDFS的元數據的倉庫。系統設計成用戶的實際數據不經過名字節點。

1、hadoop下的文件操作命令

1 :列出hdfs文件

~# hadoop dfs –ls /

~# hadoop fs –ls /

 

2:將文件上傳到hdfs

以下命令,將本地目錄下的a.txt上傳到hdfs下的wj目錄下,並重命名爲b.txt

Hadoop fs –put a.txt /wj/b.txt

 

也可以使用copyFromLocal命令將本目錄下的文件上傳到hdfs文件系統中:

 

3:將hdfs中的文件複製到本地系統中

通過get命令,即可以操作文件也可以操作文件夾:

操作一個文件,將hdfs上的文件/wj/a.txt保存到本地,並取名爲b.txt

以下下載整個文件到當前目錄下來,注意最後的一個點

 

4:刪除hdsf下的某個文檔

 

5:其他更多操作,可以通過查幫助獲取

 

 

2、MapReduce 範例操作-測試字符統計

先向服務器上傳一文件:

執行統計:

root@linux:/home/wangjian#hadoop fs -copyFromLocal a.txt /wj/a.txt

root@linux:/home/wangjian#cd /opt/hadoop-0.20.2/

root@linux:/opt/hadoop-0.20.2#hadoop jar hadoop-0.20.2-examples.jar wordcount /wj/a.txt /wj/result2

4、查看結果:

默認情況下結果文件名爲:/wj/result2/part-0000

 

root@linux:/opt/hadoop-0.20.2#hadoop fs -cat /wj/result2/part*

 

 

4、Java操作hdfs示例

1、配置Eclipse的插件

       (非分佈式,支持本地)

       在eclipse3.6中安裝map/redurce插件:

 

選擇map/red視圖:

 

選擇添加新地址:

 

輸入以下信息:

 

配置成功後顯示在HDFSLocation顯示以下信息:

左圖顯示的都是服務器的hdsf文件系統。可以方便的進行上傳和下載。

 

 

2、Java代碼

書寫代碼之前,必須要建立一個新的map/red項目:

1、上傳本地文件到HDFS

創建一個Java源代碼類:

輸入以下代碼:(圖)

源代碼如下:

packagecn.itcast.one;

importorg.apache.hadoop.conf.Configuration;

importorg.apache.hadoop.fs.FileStatus;

importorg.apache.hadoop.fs.FileSystem;

importorg.apache.hadoop.fs.Path;

/**

 * 上傳本地文件到hdfs

 */

public class One{

       public static void main(String[] args)throws Exception {

              Configuration conf =

                     new Configuration();

              FileSystem hdfs = FileSystem.get(conf);

              Path src = new Path("c:/a.txt");//本地文件

              Path dst = newPath("/wj");//hdfs文件

              hdfs.copyFromLocalFile(src, dst);

              System.err.println("文件上傳成功至:"+conf.get("fs.default.name"));

              //列出服務器上目前擁有的文件

              FileStatus[] fs =hdfs.listStatus(dst);

              for(FileStatus f:fs){

                     System.err.println(f.getPath());

              }

       }

}

 

使用map/red運行map方法:

運行完成以後,應該可以/wj/目錄下發現一個新的文本文件:

 

2、創建HDFS文件

通過FileSystem.create(Pathf)可以在HDFS上創建文件,其中f爲文件的完整路徑:

注意是文件,而不是文件夾。

以下是源代碼:

packagecn.itcast.one;

importorg.apache.hadoop.conf.Configuration;

importorg.apache.hadoop.fs.FSDataOutputStream;

importorg.apache.hadoop.fs.FileSystem;

importorg.apache.hadoop.fs.Path;

public classCreatePath {

       public static void main(String[] args)throws Exception {

              Configuration conf =

                     new Configuration();

              FileSystem fs = FileSystem.get(conf);

              //在HDSF上創建一個文件

              FSDataOutputStreamout=fs.create(new Path("/wj/c.txt"));

              //寫入一行數據,必須使用UTF-8

              out.writeUTF("Hell使用UTF-8");

              out.close();

       }

}

 

3、重命名HDFS文件

 

4、刪除hdfs文件

       通過FileSystem.delete(Path f,Booleanrecursive)可以刪除指定的HDSF文件,其中f 爲完整的路徑,cecursive用來確定是否進行遞歸刪除:

5、查看hdfs最後修改時間

FileSystem.getModificationTime()可以查看HDFS文件的最後修改時間。

 

6、查看某個HDFS文件是否存在

       FileSystem.exists(Pathf)可以查看某個HDFS文件是否存在。

7、查找某個文件在HDFS集羣中的位置

       FileSystem.getFileBlockLocations(FileStatusfile,long start,long len)要查找指定文件在HDFS集羣上的位置:

packagecn.itcast.one;

importorg.apache.hadoop.conf.Configuration;

importorg.apache.hadoop.fs.BlockLocation;

importorg.apache.hadoop.fs.FileStatus;

importorg.apache.hadoop.fs.FileSystem;

importorg.apache.hadoop.fs.Path;

public classFindFile {

       public static void main(String[] args)throws Exception {

              Configuration conf =

                     new Configuration();

              FileSystem fs =FileSystem.get(conf);

              //必須是一個具體的文件

              Path path = newPath("/wj/a.txt");

              //文件狀態

              FileStatus fileStatus =fs.getFileStatus(path);

              //文件塊

              BlockLocation[] blockLocations=

                     fs.getFileBlockLocations(fileStatus,0,fileStatus.getLen());

              int blockLen =blockLocations.length;

              System.err.println(blockLen);

              for(int i=0;i<blockLen;i++){

                     //主機名

                     String[] hosts =blockLocations[i].getHosts();

                     for(String host:hosts){

                            System.err.println(host);

                     }

              }

       }

}

 

8、獲取 HDFS集羣上所有節點名稱

       通過DatanodeInfo.getHostName()可以獲取HDFS集羣上的所有節點名稱:

packagecn.itcast.one;

importorg.apache.hadoop.conf.Configuration;

importorg.apache.hadoop.fs.FileSystem;

importorg.apache.hadoop.hdfs.DistributedFileSystem;

importorg.apache.hadoop.hdfs.protocol.DatanodeInfo;

/**

 * 獲取所有主機節點

 */

public class GetNodes{

       public static void main(String[] args)throws Exception {

              Configuration conf =

                     new Configuration();

              FileSystem fs =FileSystem.get(conf);

              //強轉成分佈式文件對象

              DistributedFileSystem hdfs =

                     (DistributedFileSystem) fs;

              //獲取節點信息-數組

              DatanodeInfo[] dis =hdfs.getDataNodeStats();

              for(DatanodeInfo info : dis){

                     String name =info.getHostName();

                     System.err.println(name);

              }

       }

}

 

 

 

Configuration

FileSystem

 

Mapper

Redurcer

 

 

3、Map/red的java代碼-wordcount

其實WordCount並不難,只是一下子接觸到了很多的API,有一些陌生,還有就是很傳統的開發相比,map-reduce確實是一種新的編程理 念,爲了讓各位新手少走彎路,我將WordCount中的很多API都做了註釋,其實這些方法搞明白了以後程序就很簡單了,無非就是將一句話分詞,先用 map處理再用reduce處理,最後再main函數中設置一些信息,然後run(),程序就結束了。好了,不廢話,直接上代碼:

 

       主要的幾個核心類說明:

l Mapper<T,T,T,T>- 用於mapper分組處理數據

它可以設置的泛型包括:

n Text :hadoop的Text對應java.lang.String類型

n IntWritable :對應的爲Integer類型。

n LongWritable :對應的爲Long類型。

 

l Reducer類用於對mapper以後結果進行合併處理:

 

1、以下自己實現的wordcount代碼:

以下是完整源代碼:

packagecn.itcast.count;

importjava.io.IOException;

importjava.util.StringTokenizer;

import org.apache.hadoop.conf.Configuration;

import org.apache.hadoop.fs.Path;

import org.apache.hadoop.io.IntWritable;

import org.apache.hadoop.io.Text;

import org.apache.hadoop.mapreduce.Job;

import org.apache.hadoop.mapreduce.Mapper;

import org.apache.hadoop.mapreduce.Reducer;

importorg.apache.hadoop.mapreduce.lib.input.FileInputFormat;

importorg.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

public class MyWordCount {

       //Mapper<KEYIN,VALUEIN, KEYOUT, VALUEOUT>//參數說明

       publicstatic class MyMapper extends Mapper<Object,Text,Text, IntWritable>{

              privatefinal static IntWritable one = new IntWritable(1);//類似於int類型

              privateText word = new Text();                         //可以理解成String類型

              publicvoid map(Object key, Text value, Context context)

                                      throws IOException ,InterruptedException {

                     System.err.println(key+","+value);

                     //默認情況下即根據空格分隔字符串

                     StringTokenizeritr = new StringTokenizer(value.toString());

                     while(itr.hasMoreTokens()){

                            word.set(itr.nextToken());

                            context.write(word,one);

                     }

              };

       }

       //Reducer<KEYIN,VALUEIN, KEYOUT, VALUEOUT>

       publicstatic class MyReducer

                                    extends Reducer<Text,IntWritable,Text, IntWritable>{

              privateIntWritable result = new IntWritable();

              protectedvoid reduce(Text key, Iterable<IntWritable> values,

                                                                      Contextcontext)

                                                   throws IOException ,InterruptedException {

                     System.err.println(key+","+values);

                     intsum=0;

                     for(IntWritableval:values){

                            sum+=val.get();

                     }

                     result.set(sum);

                     context.write(key,result);//這是最後結果

              };

       }

       publicstatic void main(String[] args) throws Exception {

              //聲明配置信息

              Configurationconf = new Configuration();

              //聲明Job

              Jobjob = new Job(conf,"Word Count");

              //設置工作類

              job.setJarByClass(MyWordCount.class);

              //設置mapper類

              job.setMapperClass(MyMapper.class);

              //可選

              job.setCombinerClass(MyReducer.class);

              //設置合併計算類

              job.setReducerClass(MyReducer.class);

              //設置key爲String類型

              job.setOutputKeyClass(Text.class);

              //設置value爲int類型

              job.setOutputValueClass(IntWritable.class);

              //設置或是接收輸入輸出

              FileInputFormat.setInputPaths(job,newPath("/wj/b.txt"));

              FileOutputFormat.setOutputPath(job,newPath("/wj/out5"));

              //執行

              System.exit(job.waitForCompletion(true)?0:1);

       }

}

 

2、用Eclipse運行的結果

3、將文件打成jar包用hadoop jar命令運行的結果

 

4、在Eclipse中運行時出現的問題解決方案

Cannot run program “chmod”: CreateProcesserror=2

這個是說,不能執行chmod這個命令。

解決方案非常簡單。

1:關閉Eclipse。

2:將cgywin\bin加入到windows的path環境變量中。

3:啓動eclipse再用hadoop運行即可。

 

5、在Linux上安裝hadoop

在Linux中安裝hadoop包括在獨立的linux系統中安裝hadoop和在linux虛擬機下安裝hadoop。我本人使用後面的方式安裝。即在虛擬機上先安裝linux,然後再將hadoop安裝到linux下。

1、安裝VirtualBox VM虛擬機

(執行setup.exe安裝即可)

2、在Vbox中安裝Linux系統

(略,相信大家都應該會)

 

3、設置linux與windows的共享目錄

1、在沒有插入網線的情況下選擇網絡模式爲:HostOnly

2、選擇共享目錄:

3、掛載

Linux系統的/mnt目錄是掛載其他共享目錄的位置:

執行以下命令:

在linux上創建一個掛載目錄

掛載:掛載成功以後顯示不同的顏色:

 

4、安裝ssh

       Hadoop運行過程需要管理遠程hadoop守護進程。

       1、inux上安裝ssh使用以下命令:在網絡情況下執行一命令即可以安裝

       ~# sudo apt-get install ssh

如果是在非網絡情況下,則需要.deb或是.gz的安裝包:

(關於如果安裝deb包,請參考ubuntu.doc)

2、設置ssh無密碼登錄

~# ssh-keygen

輸入上面的命令後一路回車即可。

       3、拷貝生成的密碼文件,默認生成的密碼文件在用戶名目錄下的.ssh目錄下

       ~# cd ~/.ssh

    ~# cat id_rsa.pub authorized_keys

       4、測試是否可以無密碼登錄

       ~# ssh localhost

       ~# who

       一般情況下,第一次登錄會給出一個錯誤提示,退出後再次登錄即可。

配置好ssh以後,建議使用xshell遠程操作linux這樣更加方便。

       5、啓動以後輸入以下命令登錄:

      

5、安裝hadoop

1、進入目錄,將hadoop-0.20.2.tar.gz拷貝到/opt的根目錄下去:

2、進入/opt目錄安裝hadoop

~tar –zxf       hadoop-0.20.2.tag.gz

安裝成功後多了一個hadoop-0.20.2目錄:

3、設置linux環境變量

配置文件:/etc/profile

使用vim進行編輯:

~# vim        /etc/profile

 

在最後面的部分追加hadoop的bin目錄:

可以直接拷貝下面的配置,要根據具體情況做出修改:

exportJAVA_HOME=/usr/local/java/jdk1.7.0_02

exportJRE_HOME=/usr/local/java/jdk1.7.0_02/jre

exportCLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH

exportPATH=$JAVA_HOME/bin:$JRE_HOME/bin:$JAVA_HOME:$PATH

exportPATH=/opt/hadoop-0.20.2/bin:$PATH

 

4、配置完成以後,關閉窗口再將打開一個新的窗口,建議使用xshell進行操作,

輸入hadoop:

如果給出以下提示,說明配置成功:

 

6、配置hadoop

1、修改$hadoop_home/conf/core-site.xml

使用vim打開編輯:

<configuration>

<property>

<name>fs.default.name</name>

<value>hdfs://localhost:9000</value>

</property>

<property>

       <name>hadoop.tmp.dir</name>

       <value>/var/hadoop/hadoop-${user.name}</value>

</property>

</configuration>

編輯完成後,使用:wq保存退出。

 

2、修改$hadoop_home/conf/hdfs.site.xml

<configuration>

<property>

       <name>dfs.replication</name>

        <value>1</value>

</property>

</configuration>

 

               

3、修改mepred-site.xml配置文件:

 mapred.child.tmp可以是其他目錄。

<configuration>

       <property>

              <name>mapred.job.tracker</name>

              <value>localhost:9001</value>

       </property>

       <property>

              <name>mapred.child.tmp</name>

              <value>/opt/temp</value>

       </property>

</configuration>

7、啓動hadoop

 

1、在啓動hadoop之前必須要先格式化namenode

輸入:

root@linux:/opt/hadoop-0.20.2/bin#hadoop namenode -format

2、使用start-all.sh一次全部啓動

在linux環境下,使用start-all.sh可以一次全部啓動所有的節點,這一點優於在cygwin環境下。可見hadoop確實適合在linux環境下運行:

執行以下命令:

root@linux:/opt/hadoop-0.20.2/bin#start-all.sh

查看是否都啓動成功,使用jps命令:

root@linux:/opt/hadoop-0.20.2/bin#jps

如果5個節點都啓動成功,則可以正常訪問了。

3、測試字符統計

先向服務器上傳一文件:

執行統計:

root@linux:/home/wangjian#hadoop fs -copyFromLocal a.txt /wj/a.txt

root@linux:/home/wangjian#cd /opt/hadoop-0.20.2/

root@linux:/opt/hadoop-0.20.2#hadoop jar hadoop-0.20.2-examples.jar wordcount /wj/a.txt /wj/result2

4、查看結果:

默認情況下結果文件名爲:/wj/result2/part-0000

 

root@linux:/opt/hadoop-0.20.2#hadoop fs -cat /wj/result2/part*

8、停止hadoop

root@linux:/opt/hadoop-0.20.2#stop-all.sh

9、逐個啓動節點

啓動節點按以下順序進行:

Hadoop-daemon.sh負責單個啓動hadoop的節點:

root@linux:/opt/hadoop-0.20.2# hadoop-daemon.sh start namenode

starting namenode, logging to /opt/hadoop-0.20.2/bin/../logs/hadoop-root-namenode-linux.out

root@linux:/opt/hadoop-0.20.2#hadoop-daemon.sh start datanode

starting datanode, logging to /opt/hadoop-0.20.2/bin/../logs/hadoop-root-datanode-linux.out

root@linux:/opt/hadoop-0.20.2#hadoop-daemon.sh start secondarynamenode

starting secondarynamenode, logging to/opt/hadoop-0.20.2/bin/../logs/hadoop-root-secondarynamenode-linux.out

root@linux:/opt/hadoop-0.20.2#hadoop-daemon.sh start jobtracker

starting jobtracker, logging to/opt/hadoop-0.20.2/bin/../logs/hadoop-root-jobtracker-linux.out

root@linux:/opt/hadoop-0.20.2#hadoop-daemon.sh start tasktracker

starting tasktracker, logging to/opt/hadoop-0.20.2/bin/../logs/hadoop-root-tasktracker-linux.out

 

 

啓動時參數爲start即:

Hadoop-daemon.sh start namenode

關閉時參數爲stop:

Hadoop-daemon.sh stop namenode

 

(安裝好以後,在Eclipse中寫好代碼,將打好的jar文件,放到hadoop的主服務器上,執行。)

 

 

6、兩個示例

1、單詞計數:

~# hadoop jar hadoop-example-0.20.2.jar  wordcount  /data/word.txt  /data/out1

2、對一億個uuid進行排序

~# hadoop jar contrib/streamming/hadoop-0.20.2-streamming.jar  -mapper ‘cat’ –reducer  ‘wc -l’

-input /data/bigdata.txt  -output   /data/out2

 

                                                                                                                                                   楊文華

                                                                                                                                                  [email protected]

                                                                                                                                                  18024582664

發佈了32 篇原創文章 · 獲贊 4 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章