Hadoop0.20.2在Linux X64下的分佈式配置和使用
2013年3月
郭運凱
目 錄
6.1.7 hadoop-site.xml參數說明...25
6.2.3 編寫Hadoop應用程序並在集羣上運行...31
6.2.4 三種模式下編譯運行Hadoop應用程序...31
jie介紹
介紹
這是利用Vmware 9.0在一臺服務器上搭建的分佈式環境,操作系統CentOS 6.3 X64中配置Hadoop-0.20.2時的總結文檔。 Hadoop配置建議所有配置文件中使用主機名進行配置,並且機器上應在防火牆中開啓相應端口,並設置SSHD服務爲開機啓動,此外java環境變量可以在/etc/profile中配置。
1 集羣網絡環境介紹及快速部署
集羣包含五個節點:1個namenode,4個datanode,節點之間局域網連接,可以相互ping通。
所有節點均是Centos 6.3 64位系統,防火牆均禁用,sshd服務均開啓並設置爲開機啓動。
a) 首先在VMware中安裝好一臺Centos 6.3,創建hadoop用戶。假設虛擬機的名字爲NameNode
b) 關閉虛擬機,把NameNode文件夾,拷貝4份,並命名爲DataNode1,..,DataNode4
c) 用VMware打開每個DateNode,設置其虛擬機的名字
d) 打開操作系統,當彈出對話框時,選擇“I copy it”
e) 打開每個虛擬機,查看ip地址
ifconfig
現將IP地址規劃如下
10.88.106.187 |
namenode |
10.88.106.188 |
datanode1 |
10.88.106.189 |
datanode2 |
10.88.106.190 |
datanode3 |
10.88.106.191 |
datanode4 |
f) 配置NameNode
第一步,檢查機器名
#hostname
如發現不對,則修改,root用戶登陸,修改命令如下
# vim /etc/sysconfig/network
NETWORKING=yes HOSTNAME=NameNode |
依次對每個節點進行處理,修改完之後,重啓系統 #reboot
g) 修改/etc/hosts
root用戶
vim /etc/sysconfig/network
(1)namenode節點上編輯/etc/hosts文件
將所有節點的名字和IP地址寫入其中,寫入如下內容,注意註釋掉127.0.0.1行,保證內容如下:
10.88.106.187 namenode 10.88.106.188 datanode1 10.88.106.189 datanode2 10.88.106.190 datanode3 10.88.106.191 datanode4 # 127.0.0.1 centos63 localhost.localdomain localhost |
(2)將Namenode上的/etc/hosts文件複製到所有數據節點上,操作步驟如下:
root用戶登錄namenode;
執行命令:
scp /etc/hosts root@10.88.106.188:/etc/hosts
scp /etc/hosts [email protected]:/etc/hosts
scp /etc/hosts [email protected]:/etc/hosts
scp /etc/hosts [email protected]:/etc/hosts
h) 規劃系統目錄
完整路徑 |
說明 |
/usr/local/hadoop |
hadoop的主目錄 |
/usr/local/hadoop/tmp |
臨時目錄 |
/usr/local/hadoop/hdfs/name |
namenode上存儲hdfs名字空間元數據 |
usr/local/hadoop/hdfs/data |
datanode上數據塊的物理存儲位置 |
/usr/local/hadoop/mapred/local |
tasktracker上執行mapreduce程序時的本地目錄 |
/usr/local/hadoop/mapred/system |
這個是hdfs中的目錄,存儲執行mr程序時的共享文件 |
至於這裏爲什麼在/usr/local下建立,解釋如下
/usr 文件系統
/usr 文件系統經常很大,因爲所有程序安裝在這裏. /usr裏的所有文件一般來自Linux distribution;本地安裝的程序和其他東西在/usr/local下.這樣可能在升級新版系統或新distribution時無須重新安裝全部程序.
/usr/local 本地安裝的軟件和其他文件放在這裏.
小貼士:創建目錄:mkdir(make directories)
功能說明:建立目錄
語 法:mkdir [-p][--help][--version][-m <目錄屬性>][目錄名稱]
補充說明:mkdir可建立目錄並同時設置目錄的權限。
參 數:
-m<目錄屬性>或–mode<目錄屬性>建立目錄時同時設置目錄的權限。
-p或–parents若所要建立目錄的上層目錄目前尚未建立,則會一併建立上層目錄。
例:mkdir test
開始建立目錄:
在NameNode下,root用戶
[root@NameNode ~]# mkdir -p /usr/local/hadoop/tmp
[root@NameNode ~]# mkdir -p /usr/local/hadoop/hdfs/name
[root@NameNode ~]# mkdir -p /usr/local/hadoop/hdfs/data
[root@NameNode ~]# mkdir -p /usr/local/hadoop/mapred/local
[root@NameNode ~]# mkdir -p /usr/local/hadoop/mapred/system
驗證一下
可以直接進入tmp目錄,不用先建立上級目錄
修改目錄/usr/local/hadoop的擁有者(因爲該目錄用於安裝hadoop,用戶對其必須有rwx權限。)
chown -R hadoop:hadoop /usr/local/hadoop
修改前
修改後
創建完畢基礎目錄後,下一步就是設置SSH無密碼驗證,以方便hadoop對集羣進行管理。
2 SSH無密碼驗證配置
Hadoop需要使用SSH協議,namenode將使用SSH協議啓動namenode和datanode進程,datanode向namenode傳遞心跳信息可能也是使用SSH協議,這是我認爲的,還沒有做深入瞭解,datanode之間可能也需要使用SSH協議。假若是,則需要配置使得所有節點之間可以相互SSH無密碼登陸驗證。
2.1配置所有節點之間SSH無密碼驗證
(0)原理
節點A要實現無密碼公鑰認證連接到節點B上時,節點A是客戶端,節點B是服務端,需要在客戶端A上生成一個密鑰對,包括一個公鑰和一個私鑰,而後將公鑰複製到服務端B上。當客戶端A通過ssh連接服務端B時,服務端B就會生成一個隨機數並用客戶端A的公鑰對隨機數進行加密,併發送給客戶端A。客戶端A收到加密數之後再用私鑰進行解密,並將解密數回傳給B,B確認解密數無誤之後就允許A進行連接了。這就是一個公鑰認證過程,其間不需要用戶手工輸入密碼。重要過程是將客戶端A公鑰複製到B上。
因此如果要實現所有節點之間無密碼公鑰認證,則需要將所有節點的公鑰都複製到所有節點上。
(1)所有機器上生成密碼對
(a)所有節點用hadoop用戶登陸,並執行以下命令,生成rsa密鑰對:
ssh-keygen -t rsa
這將在/home/hadoop/.ssh/目錄下生成一個私鑰id_rsa和一個公鑰id_rsa.pub。
# su hadoop
ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/ hadoop /.ssh/id_rsa): 默認路徑
Enter passphrase (empty for no passphrase): 回車,空密碼
Enter same passphrase again:
Your identification has been saved in /home/ hadoop /.ssh/id_rsa.
Your public key has been saved in /home/ hadoop /.ssh/id_rsa.pub.
這將在/home/hadoop/.ssh/目錄下生成一個私鑰id_rsa和一個公鑰id_rsa.pub。
(b)將所有datanode節點的公鑰id_rsa.pub傳送到namenode上:
DataNode1上執行命令:
scp id_rsa.pub hadoop@NameNode:/home/hadoop/.ssh/ id_rsa.pub.datanode1
......
DataNodeN上執行命令:
scp id_rsa.pub hadoop@NameNode:/home/hadoop/.ssh/ id_rsa.pub.datanoden
DataNode1
DataNode2
DataNode3
DataNode4
檢查一下是否都已傳輸過來
各個數據節點的公鑰已經傳輸過來。
(c)namenode節點上綜合所有公鑰(包括自身)並傳送到所有節點上
[hadoop@NameNode .ssh]$ cat id_rsa.pub >> authorized_keys 這是namenode自己的公鑰
[hadoop@NameNode .ssh]$ cat id_rsa.pub.datanode1 >> authorized_keys
[hadoop@NameNode .ssh]$ cat id_rsa.pub.datanode2 >> authorized_keys
[hadoop@NameNode .ssh]$ cat id_rsa.pub.datanode3 >> authorized_keys
[hadoop@NameNode .ssh]$ cat id_rsa.pub.datanode4 >> authorized_keys
chmod 644 ~/.ssh/authorized_keys
使用SSH協議將namenode的公鑰信息authorized_keys複製到所有DataNode的.ssh目錄下。
scp authorized_keys data節點ip地址:/home/hadoop/.ssh
scp ~/.ssh/authorized_keyshadoop@DataNode1:/home/hadoop/.ssh/authorized_keys
scp ~/.ssh/authorized_keyshadoop@DataNode2:/home/hadoop/.ssh/authorized_keys
scp ~/.ssh/authorized_keyshadoop@DataNode3:/home/hadoop/.ssh/authorized_keys
scp ~/.ssh/authorized_keyshadoop@DataNode4:/home/hadoop/.ssh/authorized_keys
從這裏就可以看到,當配置好hosts之後,就可以直接以機器名來訪問各個機器,不用再記憶各個機器的具體IP地址,當集羣中機器很多且IP不連續時,就發揮出威力來了。
從上圖可以看到,將authorized_keys分發給各個節點之後,可以直接ssh登錄,不再需要密碼。
這樣配置過後,namenode可以無密碼登錄所有datanode,可以通過命令
“ssh DataNode1(2,3,4)”來驗證。
配置完畢,在namenode上執行“ssh NameNode,所有數據節點”命令,因爲ssh執行一次之後將不會再詢問。在各個DataNode上也進行“ssh NameNode,所有數據節點”命令。
至此,所有的節點都能相互訪問,下一步開始配置jdk
3 JDK安裝和Java環境變量配置
3.1 安裝 JDK 1.6
1.下載JDK。
選定linux環境版本,下載到的文件是:jdk-6u41-linux-x64.bin
2.創建JDK安裝目錄。
在Linux系統硬盤系統文件夾usr/local下創建一個文件夾Java。
命令:mkdir –P /usr/local/java
3.複製JDK安裝包到系統指定文件夾。
把下載的安裝文件(jdk-6u41-linux-x64.bin )拷到linux路徑/usr/local/java下。
4.給安裝文件賦予權限。
a).進入目錄,命令:cd /usr/local/java
b).賦予權限,命令:chmod +x jdk-6u41-linux-x64.bin
(如果因權限問題執行失敗,則加上su, 即su chmod u+x jdk-6u41-linux-x64.bin )
5安裝JDK。
開始安裝,在控制檯執行命令: ./ jdk-6u41-linux-x64.bin
(如果因權限問題執行失敗,則加上su , 即sud./jdk-6u41-linux-x64.bin )
文件會被安裝到當前目錄 /usr/local/java/jdk1.6.0_41
刪除安裝文件rm jdk-6u41-linux-x64.bin
安裝完成後,修改/usr/local/java目錄擁有着爲hadoop用戶,
chown -R hadoop:hadoop /usr/local/java
然後將 /usr/local/java目錄需要複製到所有數據節點上。
3.2 Java環境變量配置
root用戶登陸,命令行中執行命令”vim /etc/profile”,並加入以下內容,配置環境變量(注意/etc/profile這個文件很重要,後面Hadoop的配置還會用到)。
# set java environment
#set java environment
JAVA_HOME=/usr/local/java/jdk1.6.0_41
PATH=$JAVA_HOME/bin:$PATH
CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export JAVA_HOME CLASSPATH PATH
保存並退出,執行以下命令使配置生效
chmod +x /etc/profile
source /etc/profile
配置完畢,在命令行中使用命令“java -version”可以判斷是否成功。在hadoop用戶下測試java –version,一樣成功。
a).輸入命令打印三個環境變量的值:
echo $JAVA_HOME
echo $CLASSPATH
echo $PATH
b).正確的結果如下:
[root@NameNode ~]# echo $JAVA_HOME
/usr/local/java/jdk1.6.0_41
[root@NameNode ~]# echo $CLASSPATH
.:/usr/local/java/jdk1.6.0_41/lib/dt.jar:/usr/local/java/jdk1.6.0_41/lib/tools.jar
[root@NameNode ~]# echo $PATH
/usr/local/java/jdk1.6.0_41/bin:/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
[root@NameNode ~]#
將Namenode上的/etc/profile複製到所有數據節點上。操作步驟如下:
root用戶登錄namenode;
執行命令:
scp /etc/profile root@(datanode1):/etc/profile
……
scp /etc/profile root@(datanoden):/etc/profile
4 Hadoop集羣配置
在namenode上執行:
Hadoop用戶登錄。
下載hadoop-0.20.2,將其解壓到/usr/local/hadoop目錄下,解壓後目錄形式是/usr/local/hadoop/ hadoop-0.20.2。使用如下命令:
tar zxvf hadoop-0.20.2.tar.gz
(1)配置Hadoop的配置文件
(a)配置hadoop-env.sh
$ vim /usr/local/hadoop/hadoop-0.20.2/conf/hadoop-env.sh
# set java environment export JAVA_HOME=/usr/local/java/jdk1.6.0_41/
export HADOOP_HOME_WARN_SUPPRESS=1 export HADOOP_CLASSPATH=/usr/local/hadoop/hadoop-0.20.2:/usr/local/hadoop/hadoop-0.20.2/lib |
(b)配置/etc/profile
#set java enviroment export HADOOP_HOME=/usr/local/hadoop/hadoop-0.20.2 export HADOOP_HOME_WARN_SUPPRESS=1 JAVA_HOME=/usr/local/java/jdk1.6.0_41 JRE_HOME=/usr/local/java/jdk1.6.0_41/jre PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$HADOOP_HOME/bin:$PATH CLASSPATH=.:$JAVA_HOME/bin/dt.jar:$JAVA_HOME/lib/tools.jar export JAVA_HOME CLASSPATH PATH |
修改完,重啓/etc/profile
[root@NameNode ~]# source /etc/profile
(c)配置conf/hadoop-site.xml
Hadoop-0.20.2之後的版本請分別配置core-site.xml,hdfs-site.xml和mapred-site.xml三個配置文件。
配置文件名(xml) |
字段名 |
字段值 |
說明 |
core-site |
fs.default.name |
hdfs://NameNode:9000 |
|
hadoop.tmp.dir |
/usr/local/hadoop/tmp |
臨時目錄 |
|
hdfs-site |
dfs.name.dir |
/usr/local/hadoop/hdfs/name |
namenode上存儲hdfs名字空間元數據 |
dfs.data.dir |
usr/local/hadoop/hdfs/data |
datanode上數據塊的物理存儲位置 |
|
dfs.replication |
3 |
副本個數,不配置默認是3,應小於datanode機器數量 |
|
mapred-site |
mapred.job.tracker |
NameNode:9001 |
jobtracker標識:端口號,不是URI |
mapred.local.dir |
/usr/local/hadoop/mapred/local |
tasktracker上執行mapreduce程序時的本地目錄 |
|
mapred.system.dir |
/usr/local/hadoop/mapred/system |
這個是hdfs中的目錄,存儲執行mr程序時的共享文件 |
core-site.xml <?xml version="1.0"?> <?xml-stylesheet type="text/xsl" href="configuration.xsl"?> <configuration> <property> <name>fs.default.name</name> <value>hdfs://NameNode:9000</value> </property>
<property> <name>hadoop.tmp.dir</name> <value>/usr/local/hadoop/tmp</value> </property> </configuration> |
hdfs-site.xml <?xml version="1.0"?> <?xml-stylesheet type="text/xsl" href="configuration.xsl"?> <!-- Put site-specific property overrides in this file. --> <configuration> <property> <name>dfs.name.dir</name> <value>/usr/local/hadoop/hdfs/name</value> </property> <property> <name>dfs.data.dir</name> <value>/usr/local/hadoop/hdfs/data</value> </property> <property> <name>dfs.replication</name> <value>3</value> </property> </configuration> |
mapred-site.xml
mapred-site.xml <?xml version="1.0"?> <?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<!-- Put site-specific property overrides in this file. --> <configuration> <property> <name>mapred.job.tracker</name> <value>NameNode:9001</value> </property>
<property> <name>mapred.local.dir</name> </property> <property> <name>mapred.system.dir</name> </property> </configuration> |
(d)配置masters文件,加入namenode的主機名
NameNode |
(e)配置slaves文件, 加入所有datanode的主機名
DataNode1 DataNode2 DataNode3 DataNode4 |
(2)複製配置好的各文件到所有數據節點上。
在每個節點,首先建立文件夾
mkdir /usr/local/hadoop
然後更改文件夾的屬主
chown hadoop:hadoop /usr/local/hadoop/
在NameNode
root用戶下:
scp /etc/hosts DataNode1:/etc/hosts
scp /etc/profile DataNode1:/etc/profile
scp /usr/java -r DataNode1:/usr/java
……
scp /etc/hosts DataNode4:/etc/hosts
scp /etc/profile DataNode4:/etc/profile
scp /usr/local/java/* -r DataNode4:/usr/local/java
scp -r /usr/local/hadoop/* hadoop@DataNode1:/usr/local/hadoop
scp -r /usr/local/hadoop/* hadoop@DataNode2:/usr/local/hadoop
scp -r /usr/local/hadoop/* hadoop@DataNode3:/usr/local/hadoop
scp -r /usr/local/hadoop/* hadoop@DataNode4:/usr/local/hadoop
複製完之後,需要在各個datanode節點上執行
chown -R hadoop:hadoop /usr/local/java
chown -R hadoop:hadoop /usr/local/hadoop (在各個節點上看,已經屬於hadoop了,這裏執行一次,以防萬一)
5 Hadoop集羣啓動
Namenode執行:
格式化namenode,格式化後在namenode生成了hdfs/name文件夾
bin/hadoop namenode –format
[hadoop@namenode bin]$ bin/start-all.sh
[hadoop@namenode bin]$ start-all.sh
************************************************************/
[hadoop@NameNode bin]$ start-all.sh
starting namenode, logging to /usr/local/hadoop/hadoop-0.20.2/bin/../logs/hadoop-hadoop-namenode-NameNode.out
DataNode4: starting datanode, logging to /usr/local/hadoop/hadoop-0.20.2/bin/../logs/hadoop-hadoop-datanode-DateNode4.out
DataNode2: starting datanode, logging to /usr/local/hadoop/hadoop-0.20.2/bin/../logs/hadoop-hadoop-datanode-DataNode2.out
DataNode1: starting datanode, logging to /usr/local/hadoop/hadoop-0.20.2/bin/../logs/hadoop-hadoop-datanode-DataNode1.out
DataNode3: starting datanode, logging to /usr/local/hadoop/hadoop-0.20.2/bin/../logs/hadoop-hadoop-datanode-DataNode3.out
NameNode: starting secondarynamenode, logging to /usr/local/hadoop/hadoop-0.20.2/bin/../logs/hadoop-hadoop-secondarynamenode-NameNode.out
starting jobtracker, logging to /usr/local/hadoop/hadoop-0.20.2/bin/../logs/hadoop-hadoop-jobtracker-NameNode.out
DataNode2: starting tasktracker, logging to /usr/local/hadoop/hadoop-0.20.2/bin/../logs/hadoop-hadoop-tasktracker-DataNode2.out
DataNode1: starting tasktracker, logging to /usr/local/hadoop/hadoop-0.20.2/bin/../logs/hadoop-hadoop-tasktracker-DataNode1.out
DataNode3: starting tasktracker, logging to /usr/local/hadoop/hadoop-0.20.2/bin/../logs/hadoop-hadoop-tasktracker-DataNode3.out
DataNode4: starting tasktracker, logging to /usr/local/hadoop/hadoop-0.20.2/bin/../logs/hadoop-hadoop-tasktracker-DateNode4.out
[hadoop@namenode bin]$
啓動hadoop所有進程,
bin/start-all.sh(或者先後執行start-dfs.sh和start-mapreduce.sh)。
可以通過以下啓動日誌看出,首先啓動namenode,然後啓動datanode1,datanode4, datanode2,datanode3,然後啓動secondarynamenode。再啓動jobtracker,然後啓動tasktracker2, tasktracker1,tasktracker4最後啓動tasktracker3。
namenode上用java自帶的小工具jps查看進程
每個datanode上查看進程
在這裏需要對每個NameNode進行檢查,當發現用JPS命令而沒有發現DataNode時,需要對集羣進行重新格式化。
在namenode上查看集羣狀態
bin/ hadoop dfsadmin -report
Hadoop查看工作情況:http:// namenode ip地址:50030
Hadoop 的web 方式查看:http://namenode ip地址:50070
6 Hadoop使用
Hadoop有兩個重要的模塊:MapReduce和HDFS,HDFS是一個分佈式文件系統,用於存儲數據,MapReduce是一個編程框架,Hadoop中運行的程序均是MapReduce作業,一個作業分爲若干個Map任務和Reduce任務。
6.1 客戶機與HDFS進行交互
6.1.1 客戶機配置
可以查看HDFS中的數據,向HDFS中寫入數據。
(1)選擇一臺機器,該機器可以是Hadoop集羣中的節點,也可以是集羣之外的機器。下面說明在集羣之外的客戶機上如何操作與HDFS交互,集羣之內的節點省去配置過程。
(2)集羣之外的機器請保證和Hadoop集羣是網絡連通的,直接將NameNode的hadoop文件夾scp過去即可
(3)按照以上步驟配置完成後,即可在客戶機的命令行中執行命令,查看HDFS文件系統。
6.1.2 列出HDFS根目錄/下的文件
[hadoop@namenode bin]$ bin/hadoop dfs -ls /
第一列是目錄權限,第二列的hadoop是目錄擁有者,第三列是組名,第4列是目錄大小(單位是B),第5列是目錄的絕對路徑。這裏表示/目錄下有三個目錄。這裏的用戶hadoop是安裝hadoop的用戶,是超級用戶,相當於Linux操作系統的root用戶,組supergroup相當於root用戶組。
6.1.3 HDFS用戶管理
創建HDFS用戶需要使用hadoop用戶登錄客戶機器,並且執行hadoop相關命令。由於Hadoop默認當前HDFS中的用戶就是當前登錄客戶機的用戶,所以當前HDFS用戶即爲Hadoop超級用戶hadoop。
Hadoop似乎沒有提供創建用戶的命令,但要在HDFS中創建用戶和用戶組可以這樣做。
(i)Hadoop超級用戶hadoop在hdfs中創建目錄/user/root,
即 hadoop dfs -mkdir /user/root
(ii)更改/user/root目錄所屬用戶和組,
即bin/hadoop dfs -chown -R root:root /user/root,命令執行完畢Hadoop將默認創建有用戶root,用戶組root。
注意:若此處沒有指定組,則默認將root用戶分配到supergroup組, bin/hadoop dfs -chown -R root /user/root
(ii)這樣就相當於在hdfs中創建了用戶root,組root。並且當前客戶機的root用戶對hdfs中的/user/root目錄進行rwx。
6.1.5 複製本地數據到HDFS中
[hadoop@namenode bin]# bin/hadoop dfs –copyFromLocal /local/x /user/root/
執行以上命令即能將本地數據上傳到HDFS中,上傳的文件將會被分塊,並且數據塊將物理存儲在集羣數據節點的hadoop-site.xml文件中的dfs.data.dir參數指定的目錄下,用戶可以登錄數據節點查看相應數據塊。
HDFS中一個文件對應若干數據塊,如果文件小於塊大小(默認64M),則將會存儲到一個塊中,塊大小即文件大小。若文件很大,則分爲多個塊存儲。
6.1.6 數據副本說明
Hadoop-site.xml文件中的dfs.replication參數指定了數據塊的副本數量。一個文件被分爲若干數據塊,其所有數據塊副本的名字和元數據都是一樣的,例如下圖顯示了上傳一個目錄(包含兩個小文件)到HDFS後數據節點中數據塊情況:
圖 節點一上的副本
圖 節點二上的副本
6.1.7 hadoop-site.xml參數說明
(1) hadoop.tmp.dir
該參數默認值是“/tmp/hadoop-{當前登錄用戶名}”。
它是本地路徑,當第一次啓動Hadoop集羣進程時在namenode節點的本地創建該目錄,其作用是存儲相關臨時文件。
(2)mapred.system.dir
該參數默認值是${hadoop.tmp.dir}/mapred/system,它所表示的目錄是hdfs中的路徑,是相對於dfs.default.name的路徑,即它在hdfs中的絕對路徑是{$dfs.default.name}/{$mapred.system.dir}。
該參數指定的目錄的作用是當作業運行時,存儲作業相關文件,供tasktracker節點共享。
一般hdfs系統中/目錄下可以看到該參數指定的目錄,如
[hadoop@namenode bin]$ hadoop dfs -lsr /
其他參數參見hadoop-default.xml中的說明。
6.1.8 HDFS中的路徑
首先請查閱資料,把握URI的概念。在HDFS中,例如下面這些形式均是URI(注意不是URL,URI概念比URL更廣)。例如file:///,hdfs://x/y/z,/x/y/z,z。
HDFS路徑應該可以分爲三種:絕對URI路徑,即
hdfs://namenode:端口/xxxx/xxxx
這種形式;HDFS絕對路徑 ,例如/user或者///user,注意使用/或者///表示根目錄,而不能使用//;HDFS相對路徑,例如x,此路徑往往是相對於當前用戶主目錄/user/用戶名而言,例如x對應的HDFS絕對路徑是/user/hadoop/x。
6.1.8 Hadoop相關命令
Hadoop提供一系列的命令,在bin中,例如bin/hadoop fs –x;bin/hadoop namenode –x等等。其中有些命令只能在namenode上執行。
bin下還有一些控制腳本,例如start-all.sh、start-mapred.sh、start-dfs.sh等等。數據節點上運行start-all.sh將會只啓動本節點上的進程,如datanode、tasktracker。
6.2 客戶機提交作業到集羣
6.2.1 客戶機配置
可以在客戶機上向Hadoop集羣提交作業。
(1)選擇一臺機器,該機器可以是Hadoop集羣中的節點,也可以是集羣之外的機器。下面說明在集羣之外的客戶機上如何向hadoop提交作業,集羣之內的節點省去配置過程。
(2)集羣之外的機器請保證和Hadoop集羣是網絡連通的,並且安裝了Hadoop(解壓安裝包即可)並在conf/hadoop-site.xml中做了相關配置,至少配置如下:
core-site.xml
<?xml version="1.0"?> <?xml-stylesheet type="text/xsl" href="configuration.xsl"?> <configuration> <property> <name>fs.default.name</name> <value>hdfs://NameNode:9000</value> </property> </configuration> |
mapred-site.xml
<?xml version="1.0"?> <?xml-stylesheet type="text/xsl" href="configuration.xsl"?> <configuration> <property> <name>mapred.job.tracker</name> <value>NameNode:9001</value> </property> </configuration>
|
(3)按照以上步驟配置完成後,即可在客戶機的命令行中執行命令,向hadoop提交作業。
6.2.2 一個測試例子WordCount
計算輸入文本中詞語數量的程序WordCount在Hadoop主目錄下的java程序包hadoop-0.20.2-examples.jar中,執行步驟如下:
(1)上傳數據到HDFS中
[hadoop@NameNode hadoop-0.20.2]$ hadoop fs -copyFromLocal /usr/local/hadoop/hadoop-0.20.2/README.txt input
[hadoop@NameNode hadoop-0.20.2]$ hadoop dfs -ls input
Found 1 items
-rw-r--r-- 3 hadoop supergroup 1366 2013-03-11 18:34 /user/hadoop/input
Datanode1下的數據
DataNode2下的數據
DataNode3下沒有數據
DataNode4下的數據
在這個集羣中,定義數據的副本爲3,集羣中有4個節點,數據分別在DataNode1、DataNode2、DataNode4 這三處存放。
(2)執行命令,提交作業
[hadoop@namenode hadoop-0.20.2]$ bin/hadoop jar hadoop-0.20.2-examples.jar wordcount input output
[hadoop@NameNode hadoop-0.20.2]$ bin/hadoop jar hadoop-0.20.2-examples.jar wordcount input output 13/03/11 18:42:42 INFO input.FileInputFormat: Total input paths to process : 1 13/03/11 18:42:42 INFO mapred.JobClient: Running job: job_201303111827_0001 13/03/11 18:42:43 INFO mapred.JobClient: map 0% reduce 0% 13/03/11 18:42:52 INFO mapred.JobClient: map 100% reduce 0% 13/03/11 18:43:04 INFO mapred.JobClient: map 100% reduce 100% 13/03/11 18:43:06 INFO mapred.JobClient: Job complete: job_201303111827_0001 13/03/11 18:43:06 INFO mapred.JobClient: Counters: 17 13/03/11 18:43:06 INFO mapred.JobClient: Job Counters 13/03/11 18:43:06 INFO mapred.JobClient: Launched reduce tasks=1 13/03/11 18:43:06 INFO mapred.JobClient: Launched map tasks=1 13/03/11 18:43:06 INFO mapred.JobClient: Data-local map tasks=1 13/03/11 18:43:06 INFO mapred.JobClient: FileSystemCounters 13/03/11 18:43:06 INFO mapred.JobClient: FILE_BYTES_READ=1836 13/03/11 18:43:06 INFO mapred.JobClient: HDFS_BYTES_READ=1366 13/03/11 18:43:06 INFO mapred.JobClient: FILE_BYTES_WRITTEN=3704 13/03/11 18:43:06 INFO mapred.JobClient: HDFS_BYTES_WRITTEN=1306 13/03/11 18:43:06 INFO mapred.JobClient: Map-Reduce Framework 13/03/11 18:43:06 INFO mapred.JobClient: Reduce input groups=131 13/03/11 18:43:06 INFO mapred.JobClient: Combine output records=131 13/03/11 18:43:06 INFO mapred.JobClient: Map input records=31 13/03/11 18:43:06 INFO mapred.JobClient: Reduce shuffle bytes=1836 13/03/11 18:43:06 INFO mapred.JobClient: Reduce output records=131 13/03/11 18:43:06 INFO mapred.JobClient: Spilled Records=262 13/03/11 18:43:06 INFO mapred.JobClient: Map output bytes=2055 13/03/11 18:43:06 INFO mapred.JobClient: Combine input records=179 13/03/11 18:43:06 INFO mapred.JobClient: Map output records=179 13/03/11 18:43:06 INFO mapred.JobClient: Reduce input records=131 [hadoop@NameNode hadoop-0.20.2]$ |
命令執行完畢,在頁面http://namenodeip:50030/中能夠看到作業執行情況。
(3)程序輸出
程序將統計input目錄下的所有文本文件中詞語的數量,並將結果輸出到hdfs的output目錄下的part-00000文件中。這裏的output目錄是程序生成的目錄,程序運行前不可存在。執行以下命令可以查看結果。
[hadoop@namenode hadoop-0.20.2]$ hadoop fs -ls output
Found 2 items
drwxr-xr-x - hadoop supergroup 0 2013-03-09 23:35 /user/hadoop/output/_logs
-rw-r--r-- 3 hadoop supergroup 127741 2013-03-09 23:35 /user/hadoop/output/part-r-00000
6.2.3 編寫Hadoop應用程序並在集羣上運行
這裏介紹一個向HDFS中寫入數據的例子(注意不是MR程序)來說明編寫Hadoop應用程序並放到集羣上運行的步驟。
(1)客戶端編寫應用程序並編譯運行,進行測試。
編寫程序一般需要引入hadoop相關jar包或者直接使用hadoop整個程序包,相關代碼見附錄。
(2)打包應用程序
在eclipse中打包成jar文件存儲到相應目錄下,例如/hadoop/ jarseclipse/dfsOperator.jar。
(3)上傳數據到HDFS
bin/hadoop fs –copyFromLocal local dst
本實例中不需要上傳數據,一般的程序都涉及輸入數據。
(4)執行應用程序
bin/hadoop jar x.jar jar包中主類名 [輸入參數] [輸出參數]
這裏使用的命令是:
bin/hadoop jar ~/jarseclipse/dfsOperator.jar DFSOperator
6.2.4 三種模式下編譯運行Hadoop應用程序
集羣是完全分佈式環境,Hadoop的MR程序將以作業的形式提交到集羣中運行。我們在客戶端編寫Hadoop應用程序時一般是在僞分佈式模式或單擊模式下進行編譯,然後將編譯無誤的程序打成包提交到Hadoop集羣中,當然我們仍可直接讓程序在Hadoop集羣中編譯。
(1)讓Hadoop應用程序在直接在集羣中編譯
將hadoop整個包導入eclipse中,配置core-site.xml和mapred-site.xml文件如下:
core-site.xml <configuration> <property> <name>fs.default.name</name> <value>hdfs://NameNode:9000</value> </property> </configuration>
mapred-site.xml <configuration> <property> <name>mapred.job.tracker</name> <value> NameNode:9001</value> </property> </configuration> |
編寫應用程序,編譯運行,此時程序將直接在Hadoop集羣中運行。此種方法在開發中不建議使用,以防止破壞集羣環境。
(2)單機模式下編譯Hadoop應用程序
將hadoop整個包導入eclipse中, hadoop-site.xml文件不做任何配置,保留默認的空配置。
單機模式下運行Hadoop應用程序時,程序使用的是本地文件系統。
(3)僞分佈式模式下編譯Hadoop應用程序
在單機上配置Hadoop僞分佈式模式,配置文件hadoop-site.xml如下:
core-site.xml <?xml version="1.0"?> <?xml-stylesheet type="text/xsl" href="configuration.xsl"?> <!-- Put site-specific property overrides in this file. --> <configuration> <property> <name>fs.default.name</name> <value>hdfs://localhost:9000</value> </property> </configuration> hdfs-site.xml <?xml version="1.0"?> <?xml-stylesheet type="text/xsl" href="configuration.xsl"?> <!-- Put site-specific property overrides in this file. --> <configuration> <property> <name>dfs.replication</name> <value>1</value> </property> </configuration>
mapred-site.xml <?xml version="1.0"?> <?xml-stylesheet type="text/xsl" href="configuration.xsl"?> <!-- Put site-specific property overrides in this file. --> <configuration> <property> <name>mapred.job.tracker</name> <value>localhost:9001</value> </property> </configuration> |
使用bin/start-all.sh啓動僞分佈式集羣。
將hadoop整個包導入eclipse中,並將hadoop-site.xml文件配置爲以上一樣的內容。(或者直接將上面的hadoop目錄導入eclipse中)。
編寫應用程序並運行,此時程序將在僞分佈式模式下運行,使用的是HDFS。
6.2.5 提交多個作業到集羣
提交一個後,可以繼續提交,這樣集羣中將有多個作業,Hadoop有一個作業隊列,可以在以下網址中查看。
http://10.88.106.187:50030/jobqueue_details.jsp?queueName=default
涉及多個作業時,Hadoop將對作業進行調度,默認調度方式是基於優先級的FIFO方式。
更改作業優先級命令
作業優先級有五種:VERY_HIGH HIGH NORMAL LOW VERY_LOW
例如:
bin/hadoop job -set-priority job_201005210042_0074 VERY_HIGH
附錄:Hadoop安裝常見錯誤
1 INFOhdfs.DFSClient: Exception in createBlockOutputStreamjava.net.NoRouteToHostException: No route to host
錯誤原因: 沒有關閉防火牆
2. be replicated to 0 nodes, instead of 1
原因:多次格式化namenode,造成namenode節點的namespaceID和datanode節點的namespaceID不一致。
處理方法1:所有的datanode刪掉,重新建
處理方法2: 登上datanode,把位於{dfs.data.dir}/current/VERSION中的namespaceID改爲最新的版本即可
[hadoop@namenode current]$ cat VERSION
#Fri Dec 14 09:37:22 CST 2012
namespaceID=525507667
storageID=DS-120876865-10.4.124.236-50010-1354772633249
cTime=0
storageType=DATA_NODE
layoutVersion=-32
[hadoop@DataNode1 current]$ cat VERSION
#Mon Mar 11 18:27:58 CST 2013
namespaceID=1736724608
storageID=DS-203565513-10.88.106.188-50010-1362997678871
cTime=0
storageType=DATA_NODE
layoutVersion=-18
兩個namespaceID不一致,把DataNode節點的namespaceID修改爲NameNode的值。
3.用JPS命令,沒有發現NameNode或DataNode
處理措施:
處理措施1:將NameNode和DataNode下的tmp和hdfs/name清空,重新執行格式化。
處理措施2:將NameNode下的tmp和hdfs/name清空。將DataNode下hadoop文件夾刪除,重建。
然後用scp命令將 /usr/local/hadoop文件夾複製到各個DataNode下的/usr/local/hadoop
scp -r/usr/local/hadoop/* hadoop@DataNode1:/usr/local/hadoop
…
scp -r/usr/local/hadoop/* hadoop@DataNode4:/usr/local/hadoop