這裡示範如何在 Ubuntu Linux 的環境中,架設單節點 Hadoop 分散式運算的大資料分析測試環境。
Apache Hadoop 是一個分散式計算的架構,可用於巨量資料(big data)的處理與分析,其原理是利用多台電腦組合成為大型的 Hadoop 叢集電腦,以特殊的 HDFS 檔案系統讓大量的資料分散儲存於各個節點中,而在計算與分析資料時,則是使用 MapReduce 等演算法將計算工作分散在各個節點中平行處理,可用於 PB 級以上的資料儲存與分析。
安裝 Java 的開發與執行環境,安裝流程請參考 Ubuntu Linux 安裝 Oracle 或 OpenJDK 的 Java JRE 與 JDK 步驟教學。
安裝好之後,確認一下 java
是否正常。
java -version
java version "1.8.0_121" Java(TM) SE Runtime Environment (build 1.8.0_121-b13) Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)
安裝 Hadoop 前要決定執行 Hadoop 用的帳號,如果是開發程式用的 Hadoop 測試環境,就使用一般的 Linux 使用者帳號即可。
從 Hadoop 的官方網站下載 Hadoop:
wget ftp://ftp.twaren.net/Unix/Web/apache/hadoop/common/hadoop-2.7.3/hadoop-2.7.3.tar.gz
解壓縮後,將 Hadoop 的目錄放置在要安裝的位置:
tar zxvf hadoop-2.7.3.tar.gz
sudo mv hadoop-2.7.3 /opt/
Hadoop 執行時會讀取 JAVA_HOME
環境變數來取得 Java 的執行環境,請先檢查一下自己的 JAVA_HOME
是否有設定好:
echo $JAVA_HOME
/usr/lib/jvm/java-8-oracle
若沒有設定好,可以在自己的 ~/.bash_profile
或 ~/.bashrc
中加入類似這樣的設定:
export JAVA_HOME="/usr/lib/jvm/java-8-oracle"
讓自己的帳號登入系統時就自動設定好 JAVA_HOME
環境變數。
另外一種設定方式是編輯 Hadoop 目錄下 etc/hadoop/hadoop-env.sh
這個 Hadoop 設定檔,找到其中的 JAVA_HOME
設定:
# The java implementation to use. export JAVA_HOME=${JAVA_HOME}
將 JAVA_HOME
替換為自己的 Java 安裝路徑即可。
PATH
環境變數將 Hadoop 的執行檔加入自己的 PATH
環境變數中,這樣在執行 Hadoop 時會比較方便。在 ~/.bashrc
中加入:
export HADOOP_HOME=/opt/hadoop-2.7.3 export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
直接載入 ~/.bashrc
的設定並測試執行 hadoop
指令:
source ~/.bashrc hadoop version
Hadoop 2.7.3 Subversion https://git-wip-us.apache.org/repos/asf/hadoop.git -r baa91f7c6bc9cb92be5982de4719c1c8af91ccff Compiled by root on 2016-08-18T01:41Z Compiled with protoc 2.5.0 From source with checksum 2e4ce5f957ea4db193bce3734ff29ff4 This command was run using /opt/hadoop-2.7.3/share/hadoop/common/hadoop-common-2.7.3.jar
Hadoop 有幾種執行模式,分別適用於不同的情況:
Hadoop 在安裝好的時候,預設的設定就是單機模式,所以如果您需要的 Hadoop 環境就是單機模式,那就不需要再去更動它的設定檔了。
我們可以使用 Hadoop 內建的範例測試一下 Hadoop 是否可以正常執行,首先複製一些 Hadoop 的 XML 設定檔作為測試用的文字資料:
cp -r $HADOOP_HOME/etc/hadoop input
執行內建的 MapReduce 範例程式,這個範例會將 input
中的檔案以 MapReduce 的方式,用正規表達式(regular expression)搜尋,並將結果儲存於 output
目錄中:
hadoop jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.3.jar grep input output 'dfs[a-z.]+'
在執行這個 Hadoop 範例程式時,會有相當多的訊息,執行完畢之後,會產生一個 output
目錄:
ls output/
part-r-00000 _SUCCESS
若程式執行成功的話,在 output
目錄中會建立一個 _SUCCESS
檔案,而 part-r-00000
就是執行結果:
cat output/part-r-00000
6 dfs.audit.logger 4 dfs.class 3 dfs.server.namenode. 2 dfs.period 2 dfs.audit.log.maxfilesize 2 dfs.audit.log.maxbackupindex 1 dfsmetrics.log 1 dfsadmin 1 dfs.servers 1 dfs.replication 1 dfs.file
Hadoop 的模擬分散執行模式可以讓單一台機器執行多個 Java 行程,模擬叢集電腦的執行狀況,以下是將 Hadoop 設定為模擬分散模式的設定方式。
Hadoop 主要的設定都是寫在 etc/hadoop
目錄中的 XML 檔裡面,以下是比較重要的 XML 設定檔:
core-site.xml
:Hadoop 基本設定檔。hdfs-site.xml
:HDFS 設定檔。mapred-site.xml
:MapReduce 設定檔。yarn-site.xml
:YARN 設定檔。更改 core-site.xml
設定檔內容:
<configuration> <property> <name>fs.defaultFS</name> <value>hdfs://localhost:9000</value> </property> </configuration>
更改 hdfs-site.xml
設定檔內容:
<configuration> <property> <name>dfs.replication</name> <value>1</value> </property> </configuration>
安裝 ssh 伺服器:
sudo apt-get install openssh-server
設定 ssh 金鑰認證登入:
ssh-keygen cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys chmod 0600 ~/.ssh/authorized_keys
檢查 ssh 登入是否需要密碼:
ssh localhost
HDFS 檔案系統在第一次使用前,要先進行格式化的動作:
hdfs namenode -format
啟動 NameNode 與 DataNode daemon:
start-dfs.sh
打開 NameNode 的網頁介面網址 http://localhost:50070/
,看看網頁是否可以正常顯示:
建立使用者用的目錄:
hdfs dfs -mkdir -p /user/gtwang
將資料放進 HDFS 中:
hdfs dfs -put $HADOOP_HOME/etc/hadoop input
查看一下資料:
hdfs dfs -ls input
執行 MapReduce 程式:
hadoop jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.3.jar grep input output 'dfs[a-z.]+'
將資料取回並查看結果:
hdfs dfs -get output output cat output/*
6 dfs.audit.logger 4 dfs.class 3 dfs.server.namenode. 2 dfs.period 2 dfs.audit.log.maxfilesize 2 dfs.audit.log.maxbackupindex 1 dfsmetrics.log 1 dfsadmin 1 dfs.servers 1 dfs.file
若不想取回資料,也可以直接使用以下的指令查看結果:
hdfs dfs -cat output/*
執行完畢之後,關閉 daemons:
stop-dfs.sh
如果在執行時出現類似這樣的錯誤訊息:
17/02/21 10:32:48 WARN hdfs.DFSClient: Caught exception java.lang.InterruptedException at java.lang.Object.wait(Native Method) at java.lang.Thread.join(Thread.java:1249) at java.lang.Thread.join(Thread.java:1323) at org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.closeResponder(DFSOutputStream.java:609) at org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.closeInternal(DFSOutputStream.java:577) at org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.run(DFSOutputStream.java:573)
這個看起來是 Hadoop 的 bug,暫時可以忽略它。