Apache Hadoop 入門教程

Hadoop發表於2016-09-16

Apache Hadoop 是一個由 Apache 基金會所開發的分散式系統基礎架構。可以讓使用者在不瞭解分散式底層細節的情況下,開發出可靠、可擴充套件的分散式計算應用。 Apache Hadoop 框架,允許使用者使用簡單的程式設計模型來實現計算機叢集的大型資料集的分散式處理。它的目的是支援從單一伺服器到上千臺機器的擴充套件,充分利用了每臺機器所提供本地計算和儲存,而不是依靠硬體來提供高可用性。其本身被設計成在應用層檢測和處理故障的庫,對於計算機叢集來說,其中每臺機器的頂層都被設計成可以容錯的,以便提供一個高度可用的服務。 Apache Hadoop 的框架最核心的設計就是:HDFS 和 MapRedu

原文同步至 http://waylau.com/about-hadoop/

Apache Hadoop 是一個由 Apache 基金會所開發的分散式系統基礎架構。可以讓使用者在不瞭解分散式底層細節的情況下,開發出可靠、可擴充套件的分散式計算應用。

Apache Hadoop 框架,允許使用者使用簡單的程式設計模型來實現計算機叢集的大型資料集的分散式處理。它的目的是支援從單一伺服器到上千臺機器的擴充套件,充分利用了每臺機器所提供本地計算和儲存,而不是依靠硬體來提供高可用性。其本身被設計成在應用層檢測和處理故障的庫,對於計算機叢集來說,其中每臺機器的頂層都被設計成可以容錯的,以便提供一個高度可用的服務。

Apache Hadoop 的框架最核心的設計就是:HDFS 和 MapReduce。HDFS 為海量的資料提供了儲存,而 MapReduce 則為海量的資料提供了計算。

Apache Hadoop 簡介

正如上一節 MapReduce 所提到的那樣,Apache Hadoop 受到了 Google 的 GFS 和 MapReduce 的啟發,而前者產生了 Apache Hadoop 的分散式檔案系統 NDFS (Nutch Distributed File System) ,而後者也被納入到 Apache Hadoop 作為核心元件之一。

Apache Hadoop 的雛形開始於2002年的 Apache 的 Nutch。Nutch 是一個開源 Java 實現的搜尋引擎。它提供了我們執行自己的搜尋引擎所需的全部工具,包括全文搜尋和 Web 爬蟲。

隨後在 2003 年 Google 發表了一篇技術學術論文關於 Google 檔案系統(GFS)。GFS 也就是 Google File System,是 Google 公司為了儲存海量搜尋資料而設計的專用檔案系統。

2004年 Nutch 創始人 Doug Cutting(同時也是 Apache Lucene 的創始人) 基於 Google 的 GFS 論文實現了分散式檔案儲存系統名為 NDFS。

2004年 Google 又發表了一篇技術學術論文,向全世界介紹了 MapReduce。2005年 Doug Cutting 又基於 MapReduce,在 Nutch 搜尋引擎實現了該功能。

2006年,Yahoo! 僱用了 Doug Cutting,Doug Cutting 將 NDFS 和MapReduce 升級命名為 Hadoop。Yahoo! 開建了一個獨立的團隊給 Goug Cutting 專門研究發展 Hadoop。

2008年1月,Hadoop 成為了 Apache 頂級專案。之後 Hadoop 被成功的應用在了其他公司,其中包括 Last.fm、Facebook、《紐約時報》等。

2008年2月,Yahoo! 宣佈其搜尋引擎產品部署在一個擁有1萬個核心的 Hadoop 叢集上。

2008年4月,Hadoop 打破世界記錄,稱為最快排序1TB資料的系統。有關該報導的記錄,可以參閱《Apache Hadoop Wins Terabyte Sort Benchmark》(見 https://developer.yahoo.com/blogs/hadoop/apache-hadoop-wins-terabyte-sort-benchmark-408.html)。

截止目前,Apache Hadoop 的最新版本為 2.7.3。

Apache Hadoop 它主要有以下幾個優點:

  • 高可靠性。Hadoop 按位儲存和處理資料的能力值得人們信賴。
  • 高擴充套件性。Hadoop 是在可用的計算機集簇間分配資料並完成計算任務的,這些集簇可以方便地擴充套件到數以千計的節點中。
  • 高效性。Hadoop 能夠在節點之間動態地移動資料,並保證各個節點的動態平衡,因此處理速度非常快。
  • 高容錯性。Hadoop 能夠自動儲存資料的多個副本,並且能夠自動將失敗的任務重新分配。
  • 低成本。Hadoop 是開源的,專案的軟體成本因此會大大降低。

Apache Hadoop 核心元件

Apache Hadoop 包含以下模組:

  • Hadoop Common:常見實用工具,用來支援其他 Hadoop 模組。
  • Hadoop Distributed File System(HDFS):分散式檔案系統,它提供對應用程式資料的高吞吐量訪問。
  • Hadoop YARN:一個作業排程和叢集資源管理框架。
  • Hadoop MapReduce:基於 YARN 的大型資料集的並行處理系統。

其他與 Apache Hadoop 的相關專案包括:

  • Ambari:一個基於Web 的工具,用於配置、管理和監控的 Apache Hadoop 叢集,其中包括支援 Hadoop HDFS、Hadoop MapReduce、Hive、HCatalog、HBase、ZooKeeper、Oozie、Pig 和 Sqoop。Ambari 還提供了儀表盤檢視叢集的健康,如熱圖,並能夠以使用者友好的方式來檢視的 MapReduce、Pig 和 Hive 應用,方便診斷其效能。
  • Avro:資料序列化系統。
  • Cassandra:可擴充套件的、無單點故障的多主資料庫。
  • Chukwa:資料採集系統,用於管理大型分散式系統。
  • HBase:一個可擴充套件的分散式資料庫,支援結構化資料的大表儲存。(有關 HBase 的內容,會在後面章節講述)
  • Hive:資料倉儲基礎設施,提供資料彙總以及特定的查詢。
  • Mahout:一種可擴充套件的機器學習和資料探勘庫。
  • Pig:一個高層次的資料流平行計算語言和執行框架。
  • Spark:Hadoop 資料的快速和通用計算引擎。Spark 提供了簡單和強大的程式設計模型用以支援廣泛的應用,其中包括 ETL、機器學習、流處理和圖形計算。(有關 Spark 的內容,會在後面章節講述)
  • TEZ:通用的資料流程式設計框架,建立在 Hadoop YARN 之上。它提供了一個強大而靈活的引擎來執行任意 DAG 任務,以實現批量和互動式資料的處理。TEZ 正在被 Hive、Pig 和 Hadoop 生態系統中其他框架所採用,也可以通過其他商業軟體(例如 ETL 工具),以取代的 Hadoop MapReduce 作為底層執行引擎。
  • ZooKeeper:一個高效能的分散式應用程式協調服務。(有關 ZooKeeper 的內容,會在後面章節講述)

Apache Hadoop 單節點上的安裝配置

下面將演示快速完成在單節點上的 Hadoop 安裝與配置,以便你對 Hadoop HDFS 和 MapReduce 框架有所體會。

1. 先決條件

支援平臺:

  • GNU/Linux:已經證實了 Hadoop 在 GNU/Linux 平臺上可以支援 2000 個節點的叢集;
  • Windows。本文所演示的例子都是在 GNU/Linux 平臺上執行,若在 Windows 執行,可以參閱http://wiki.apache.org/hadoop/Hadoop2OnWindows

所需軟體:

  • Java 必須安裝。Hadoop 2.7 及以後版本,需要安裝 Java 7,可以是 OpenJDK 或者是 Oracle(HotSpot)的 JDK/JRE。其他版本的 JDK 要求,可以參閱http://wiki.apache.org/hadoop/HadoopJavaVersions
  • ssh 必須安裝並且保證 sshd 一直執行,以便用 Hadoop 指令碼管理遠端Hadoop 守護程式。下面是在 Ubuntu 上的安裝的示例:
$ sudo apt-get install ssh
$ sudo apt-get install rsync

2. 下載

下載地址在 http://www.apache.org/dyn/closer.cgi/hadoop/common/

3. 執行 Hadoop 叢集的準備工作

解壓所下載的 Hadoop 發行版。編輯 etc/hadoop/hadoop-env.sh 檔案,定義如下引數:

# 設定 Java 的安裝目錄
export JAVA_HOME=/usr/java/latest

嘗試如下命令:

$ bin/hadoop

將會顯示 hadoop 指令碼的使用文件。

現在你可以用以下三種支援的模式中的一種啟動 Hadoop 叢集:

  • 本地(單機)模式
  • 偽分散式模式
  • 完全分散式模式

4. 單機模式的操作方法

預設情況下,Hadoop 被配置成以非分散式模式執行的一個獨立 Java 程式。這對除錯非常有幫助。

下面的例項將已解壓的 conf 目錄拷貝作為輸入,查詢並顯示匹配給定正規表示式的條目。輸出寫入到指定的 output 目錄。

$ mkdir input
$ cp etc/hadoop/*.xml input
$ bin/hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.3.jar grep input output 'dfs[a-z.]+'
$ cat output/*

5. 偽分散式模式的操作方法

Hadoop 可以在單節點上以所謂的偽分散式模式執行,此時每一個 Hadoop 守護程式都作為一個獨立的 Java 程式執行。

配置

使用如下的:

etc/hadoop/core-site.xml:

<configuration>
    <property>
        <name>fs.defaultFS</name>
        <value>hdfs://localhost:9000</value>
    </property>
</configuration>

etc/hadoop/hdfs-site.xml:

<configuration>
    <property>
        <name>dfs.replication</name>
        <value>1</value>
    </property>
</configuration>

免密碼 ssh 設定

現在確認能否不輸入口令就用 ssh 登入 localhost:

$ ssh localhost

如果不輸入口令就無法用 ssh 登陸 localhost,執行下面的命令:

$ ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa
$ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
$ chmod 0600 ~/.ssh/authorized_keys

執行

下面演示本地執行一個 MapReduce 的 job,以下是執行步驟。

(1)格式化一個新的分散式檔案系統:

$ bin/hdfs namenode -format

(2)啟動 NameNode 守護程式和 DataNode 守護程式:

$ sbin/start-dfs.sh

Hadoop 守護程式的日誌寫入到 $HADOOP_LOG_DIR目錄(預設是 $HADOOP_HOME/logs

(3)瀏覽 NameNode 的網路介面,它們的地址預設為:

NameNode - http://localhost:50070/

(4)建立 HDFS 目錄來執行 MapReduce 的 job:

$ bin/hdfs dfs -mkdir /user
$ bin/hdfs dfs -mkdir /user/<username>

(5)將輸入檔案拷貝到分散式檔案系統:

$ bin/hdfs dfs -put etc/hadoop input

(6)執行發行版提供的示例程式:

$ bin/hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.3.jar grep input output 'dfs[a-z.]+'

(7)檢視輸出檔案

將輸出檔案從分散式檔案系統拷貝到本地檔案系統檢視:

$ bin/hdfs dfs -get output output
$ cat output/*

或者,在分散式檔案系統上檢視輸出檔案:

$ bin/hdfs dfs -cat output/*

(8)完成全部操作後,停止守護程式:

$ sbin/stop-dfs.sh

執行在單節點的 YARN

您可以通過設定幾個引數,另外執行 ResourceManager 的守護程式和 NodeManager 守護程式以偽分散式模式在 YARN 上執行 MapReduce job。

以下是執行步驟。

(1)配置

etc/hadoop/mapred-site.xml:

<configuration>
    <property>
        <name>mapreduce.framework.name</name>
        <value>yarn</value>
    </property>
</configuration>

etc/hadoop/yarn-site.xml:

<configuration>
    <property>
        <name>yarn.nodemanager.aux-services</name>
        <value>mapreduce_shuffle</value>
    </property>
</configuration>

(2)啟動 ResourceManager 守護程式和 NodeManager 守護程式

$ sbin/start-yarn.sh

(3)瀏覽 ResourceManager 的網路介面,它們的地址預設為:

ResourceManager - http://localhost:8088/

(4)執行 MapReduce job

(5)完成全部操作後,停止守護程式:

$ sbin/stop-yarn.sh

6. 完全分散式模式的操作方法

關於搭建完全分散式模式的,請參閱下文《Apache Hadoop 叢集上的安裝配置》小節內容。

Apache Hadoop 叢集上的安裝配置

本節將描述如何安裝、配置和管理 Hadoop 叢集,其規模可從幾個節點的小叢集到幾千個節點的超大叢集。

1. 先決條件

確保在你叢集中的每個節點上都安裝了所有必需軟體,安裝 Hadoop 叢集通常要將安裝軟體解壓到叢集內的所有機器上,參考上節內容《Apache Hadoop 單節點上的安裝配置》。

通常情況下,叢集中的一臺機器被指定為 NameNode 和另一臺機器作為 ResourceManager。這些都是 master。其他服務(例如,Web 應用程式代理伺服器和 MapReduce Job History 伺服器)是在專用的硬體還是共享基礎設施上執行,這取決於負載。

在群集裡剩餘的機器充當 DataNode 和 NodeManager。這些都是 slave。

2. 在 Non-Secure Mode(非安全模式)下的配置

Hadoop 配置有兩種型別的重要配置檔案:

  • 預設只讀,包括 core-default.xmlhdfs-default.xmlyarn-default.xmlmapred-default.xml
  • 針對站點配置,包括 etc/hadoop/core-site.xmletc/hadoop/hdfs-site.xmletc/hadoop/yarn-site.xmletc/hadoop/mapred-site.xml

另外,你能夠配置 bin 目錄下的 etc/hadoop/hadoop-env.shetc/hadoop/yarn-env.sh 指令碼檔案的值來控制 Hadoop 的指令碼。

為了配置 Hadoop 叢集,你需要配置 Hadoop 守護程式的執行環境和Hadoop 守護程式的配置引數。

HDFS 的守護程式有 NameNode、econdaryNameNode 和 DataNode。YARN 的守護程式有 ResourceManager、NodeManager 和 WebAppProxy。若 MapReduce 在使用,那麼 MapReduce Job History Server 也是在執行的。在大型的叢集中,這些一般都是在不同的主機上執行。

配置 Hadoop 守護程式的執行環境

管理員應該利用etc/hadoop/hadoop-env.shetc/hadoop/mapred-env.shetc/hadoop/yarn-env.sh 指令碼來對 Hadoop 守護程式的環境做一些自定義的配置。

至少你應該在每個遠端節點上正確配置 JAVA_HOME。

管理員能夠使用下面的表格當中的配置選項來配置獨立的守護程式:

守護程式 環境變數
NameNode HADOOP_NAMENODE_OPTS
DataNode HADOOP_DATANODE_OPTS
SecondaryNamenode HADOOP_SECONDARYNAMENODE_OPTS
ResourceManager YARN_RESOURCEMANAGER_OPTS
NodeManager YARN_NODEMANAGER_OPTS
WebAppProxy YARN_PROXYSERVER_OPTS
Map Reduce Job History Server HADOOP_JOB_HISTORYSERVER_OPTS

例如,配置 Namenode 時,為了使其能夠 parallelGC(並行回收垃圾), 要把下面的程式碼加入到etc/hadoop/hadoop-env.sh

export HADOOP_NAMENODE_OPTS="-XX:+UseParallelGC"

其它可定製的常用引數還包括:

  • HADOOP_PID_DIR——守護程式的程式 id 存放目錄;
  • HADOOP_LOG_DIR——守護程式的日誌檔案存放目錄。如果不存在會被自動建立;
  • HADOOP_HEAPSIZE/YARN_HEAPSIZE——最大可用的堆大小,單位為MB。比如,1000MB。這個引數用於設定守護程式的堆大小。預設大小是1000。可以為每個守護程式單獨設定這個值。

在大多數情況下,你應該指定 HADOOP_PID_DIR 和 HADOOP_LOG_DIR 目錄,這樣它們只能由要執行 hadoop 守護程式的使用者寫入。否則會受到符號連結攻擊的可能。

這也是在 shell 環境配置裡配置 HADOOP_PREFIX 的傳統方式。例如,在/etc/profile.d中一個簡單的指令碼的配置如下:

HADOOP_PREFIX=/path/to/hadoop
export HADOOP_PREFIX
守護程式 環境變數
ResourceManager YARN_RESOURCEMANAGER_HEAPSIZE
NodeManager YARN_NODEMANAGER_HEAPSIZE
WebAppProxy YARN_PROXYSERVER_HEAPSIZE
Map Reduce Job History Server HADOOP_JOB_HISTORYSERVER_HEAPSIZE

配置 Hadoop 守護程式

這部分涉及 Hadoop 叢集的重要引數的配置

etc/hadoop/core-site.xml

引數 取值 備註
fs.defaultFS NameNode URI hdfs://host:port/
io.file.buffer.size 131072 SequenceFiles 中讀寫緩衝的大小

etc/hadoop/hdfs-site.xml

用於配置 NameNode:

引數 取值 備註
dfs.namenode.name.dir NameNode 持久儲存名稱空間及事務日誌的本地檔案系統路徑。 當這個值是一個逗號分割的目錄列表時,name table 資料將會被複制到所有目錄中做冗餘備份。
dfs.hosts / dfs.hosts.exclude 允許/排除的 DataNodes 列表。 如果有必要,使用這些檔案,以控制允許的 datanodes 的列表。
dfs.blocksize 268435456 在大型檔案系統裡面設定 HDFS 塊大小為 256MB
dfs.namenode.handler.count 100 在大數量的 DataNodes 裡面用更多的 NameNode 伺服器執行緒來控制 RPC

用於配置 DataNode:

引數 取值 備註
dfs.datanode.data.dir DataNode存放塊資料的本地檔案系統路徑,逗號分割的列表。 當這個值是逗號分割的目錄列表時,資料將被儲存在所有目錄下,通常分佈在不同裝置上。

etc/hadoop/yarn-site.xml

用於配置 ResourceManager 和 NodeManager:

引數 取值 備註
yarn.acl.enable true / false 是否啟用 ACLs。預設是 false
yarn.admin.acl Admin ACL ACL 叢集上設定管理員。 ACLs 是用逗號分隔的。預設為 * 意味著任何人。特殊值空格,意味著沒有人可以進入。
yarn.log-aggregation-enable false 配置演算法啟用日誌聚合

用於配置 ResourceManager :

引數 取值 備註
yarn.resourcemanager.address ResourceManager host:port ,用於給客戶端提交 jobs 若 host:port 設定,則覆蓋 yarn.resourcemanager.hostname 中的 hostname
yarn.resourcemanager.scheduler.address ResourceManager host:port,用於 ApplicationMasters (主節點)和 Scheduler(排程器)通訊來取得資源 若 host:port 設定,則覆蓋 yarn.resourcemanager.hostname 中的 hostname
yarn.resourcemanager.resource-tracker.address ResourceManager host:port ,用於 NodeManagers 若 host:port 設定,則覆蓋 yarn.resourcemanager.hostname 中的 hostname
yarn.resourcemanager.admin.address ResourceManager host:port ,用於管理命令 若 host:port 設定,則覆蓋 yarn.resourcemanager.hostname 中的 hostname
yarn.resourcemanager.webapp.address ResourceManager web-ui host:port,用於 web 管理 若 host:port 設定,則覆蓋 yarn.resourcemanager.hostname 中的 hostname
yarn.resourcemanager.scheduler.class ResourceManager Scheduler 類 CapacityScheduler (推薦)、FairScheduler(也推薦)或 FifoScheduler
yarn.scheduler.minimum-allocation-mb 分配給每個容器請求Resource Manager 的最小記憶體 單位為 MB
yarn.scheduler.maximum-allocation-mb 分配給每個容器請求Resource Manager 的最大記憶體 單位為 MB
yarn.resourcemanager.nodes.include-path / yarn.resourcemanager.nodes.exclude-path 允許/拒絕的NodeManager 的列表 如果有必要,用這些檔案來控制列出的允許的 NodeManager

用於配置 NodeManager :

引數 取值 備註
yarn.nodemanager.resource.memory-mb NodeManager 可用的實體記憶體 定義在 NodeManager 上的全部資源,用來執行容器。
yarn.nodemanager.vmem-pmem-ratio task 使用虛擬記憶體的最大比例,可能超過實體記憶體 每個 task 使用的虛擬記憶體可能超過它的實體記憶體, 虛擬記憶體靠這個比率來進行限制。這個比率限制的在 NodeManager 上task 使用的虛擬記憶體總數,可能會超過它的實體記憶體。
yarn.nodemanager.local-dirs 在本地檔案系統裡,寫入中間資料的地方的路徑。多個路徑就用逗號進行隔開。 多個路徑有助於分散磁碟I/O
yarn.nodemanager.log-dirs 在本地檔案系統裡,寫入日誌的地方的路徑。多個路徑就用逗號進行隔開。 多個路徑有助於分散磁碟I/O
yarn.nodemanager.log.retain-seconds 10800 日誌檔案在NodeManager 上儲存的預設時間(單位為秒),僅僅適合在日誌聚合關閉的時候使用。
yarn.nodemanager.remote-app-log-dir /logs 在應用程式完成的時候,應用程式的日誌將移到這個HDFS目錄。需要設定適當的許可權。 僅僅適合在日誌聚合開啟的時候使用。
yarn.nodemanager.remote-app-log-dir-suffix logs 追加到遠端日誌目錄 日誌將被聚合到${yarn.nodemanager.remote-app-log-dir}/${user}/${thisParam},僅僅適合在 log-aggregation 開啟的時候使用。
yarn.nodemanager.aux-services 、 mapreduce.shuffle 給 Map Reduce 應用程式設定 Shuffle 服務。

用於配置 History Server (需搬移到其它地方):

引數 取值 備註
yarn.log-aggregation.retain-seconds -1 保留聚合日誌的時間, -1 表示不啟用。需要注意的是,該值不能設定的太小
yarn.log-aggregation.retain-check-interval-seconds -1 檢查聚合日誌保留的時間間隔,-1 表示不啟用。需要注意的是,該值不能設定的太小

etc/hadoop/mapred-site.xml

用於配置 MapReduce 應用:

引數 取值 備註
mapreduce.framework.name yarn 執行框架設定為 Hadoop YARN.
mapreduce.map.memory.mb 1536 maps 的最大資源.
mapreduce.map.java.opts -Xmx1024M maps 子虛擬機器的堆大小
mapreduce.reduce.memory.mb 3072 reduces 的最大資源.
mapreduce.reduce.java.opts -Xmx2560M reduces 子虛擬機器的堆大小
mapreduce.task.io.sort.mb 512 任務內部排序緩衝區大小
mapreduce.task.io.sort.factor 100 在整理檔案時一次性合併的流數量
mapreduce.reduce.shuffle.parallelcopies 50 reduces 執行的最大並行複製的數量,用於獲取大量的 maps 的輸出

用於配置 MapReduce JobHistory Server:

引數 取值 備註
mapreduce.jobhistory.address MapReduce JobHistory Server host:port 預設埠是 10020.
mapreduce.jobhistory.webapp.address MapReduce JobHistory Server Web 介面 host:port 預設埠是 19888.
mapreduce.jobhistory.intermediate-done-dir /mr-history/tmp MapReduce jobs 寫入歷史檔案的目錄
mapreduce.jobhistory.done-dir /mr-history/done MR JobHistory Server 管理的歷史檔案目錄

3. 監控 NodeManager 的健康狀況

Hadoop 提供了一種機制,管理員可以配置 NodeManager 來執行提供指令碼定期確認一個節點是否健康。

管理員可以通過在指令碼中執行檢查來判斷該節點是否處於健康狀態。如果指令碼檢查到節點不健康,可以列印一個標準的 ERROR(錯誤)輸出。NodeManager 通過一些指令碼定期檢查他的輸出,如果指令碼輸出有 ERROR資訊,如上所述,該節點將報告為不健康,就將節點加入到 ResourceManager 的黑名單列表中,則任務不會分配到該節點中。然後 NodeManager 繼續跑這個指令碼,所以如果 Node 節點變為健康了,將自動的從 ResourceManager 的黑名單列表刪除,節點的健康狀況隨著指令碼的輸出,如果變為不健康,在 ResourceManager web 介面上對管理員來說是可用的。這個時候節點的健康狀況不會顯示在web介面上。

etc/hadoop/yarn-site.xml下,可以控制節點的健康檢查指令碼:

引數 取值 備註
yarn.nodemanager.health-checker.script.path Node health script 這個指令碼檢查節點的健康狀態。
yarn.nodemanager.health-checker.script.opts Node health script options 檢查節點的健康狀態指令碼選項
yarn.nodemanager.health-checker.script.interval-ms Node health script interval 執行健康指令碼的時間間隔
yarn.nodemanager.health-checker.script.timeout-ms Node health script timeout interval 健康指令碼的執行超時時間

如果只是本地硬碟壞了,健康檢查指令碼將不會設定該節點為 ERROR。但是NodeManager 有能力來定期檢查本地磁碟的健康(檢查 nodemanager-local-dirs 和 nodemanager-log-dirs 兩個目錄),當達到yarn.nodemanager.disk-health-checker.min-healthy-disks 設定的閥值,則整個節點將標記為不健康。

4. Slaves File

所有 slave 的 hostname 或者 IP 都儲存在etc/hadoop/slaves檔案中,每行一個。指令碼可以通過etc/hadoop/slaves檔案去執行多臺機器的命令。他不使用任何基於 Java 的 Hadoop 配置。為了使用這個功能,ssh 必須建立好使用賬戶才能執行 Hadoop。所以在安裝 Hadoop 的時候,需要配置 ssh 登陸。

5. Hadoop Rack Awareness(機架感知)

很多 Hadoop 元件得益於機架感知,給效能和安全性帶來了很大的提升,Hadoop 的守護程式呼叫管理配置的模組,獲取到叢集 slave 的機架資訊,更多的機架感知資訊,檢視這裡http://hadoop.apache.org/docs/r2.7.3/hadoop-project-dist/hadoop-common/RackAwareness.html

使用 HDFS 時,強烈推薦使用機架感知。

6. 日誌

Hadoop 使用 Apache log4j 作為日誌框架,編輯etc/hadoop/log4j.properties檔案來自定義日誌的配置。

7. 操縱 Hadoop 叢集

所有必備的配置都完成了,分發 HADOOP_CONF_DIR 配置檔案到所有機器,所有機器安裝 Hadoop 目錄的路徑應該是一樣的。

在一般情況下,建議 HDFS 和 YARN 作為單獨的使用者執行。在大多數安裝中,HDFS 執行 “hdfs”。YARN 通常使用“yarn”帳戶。

Hadoop 啟動

為了啟動 Hadoop 叢集,你需要啟動 HDFS 和 YARN 叢集。

第一次使用 HDFS 需要格式化。 作為 hdfs 格式化新分發的檔案系統:

[hdfs]$ $HADOOP_PREFIX/bin/hdfs namenode -format <cluster_name>

作為 hdfs,通過如下命令啟動 HDFS NameNode 到指定的節點 :

[hdfs]$ $HADOOP_PREFIX/sbin/hadoop-daemon.sh --config $HADOOP_CONF_DIR --script hdfs start namenode

作為 hdfs,通過如下命令啟動 HDFS DataNode 到每個指定的節點 :

[hdfs]$ $HADOOP_PREFIX/sbin/hadoop-daemons.sh --config $HADOOP_CONF_DIR --script hdfs start datanode

作為 hdfs,如果 etc/hadoop/slaves 和 ssh 可信任訪問已經配置,那麼所有的 HDFS 程式都可以通過指令碼工具來啟動:

[hdfs]$ $HADOOP_PREFIX/sbin/start-dfs.sh

作為 yarn,通過下面的命令啟動 YARN,執行指定的 ResourceManager :

[yarn]$ $HADOOP_YARN_HOME/sbin/yarn-daemon.sh --config $HADOOP_CONF_DIR start resourcemanager

作為 yarn,執行指令碼來啟動從機上的所有 NodeManager:

[yarn]$ $HADOOP_YARN_HOME/sbin/yarn-daemons.sh --config $HADOOP_CONF_DIR start nodemanager

作為 yarn,啟動本地化的 WebAppProxy 伺服器。如果想使用大量的伺服器來實現負載均衡,那麼它就應該執行在它們各自機器之上:

[yarn]$ $HADOOP_YARN_HOME/sbin/yarn-daemon.sh --config $HADOOP_CONF_DIR start proxyserver

作為 yarn,如果 etc/hadoop/slaves 和 ssh 可信任訪問已經配置,那麼所有的 YARN 程式都可以通過指令碼工具來啟動:

[yarn]$ $HADOOP_PREFIX/sbin/start-yarn.sh

作為 mapred,根據下面的命令啟動 MapReduce JobHistory Server :

[mapred]$ $HADOOP_PREFIX/sbin/mr-jobhistory-daemon.sh --config $HADOOP_CONF_DIR start historyserver

Hadoop 關閉

作為 hdfs,通過以下命令停止 NameNode:

[hdfs]$ $HADOOP_PREFIX/sbin/hadoop-daemon.sh --config $HADOOP_CONF_DIR --script hdfs stop namenode

作為 hdfs,執行指令碼停止在所有從機上的所有 DataNode:

[hdfs]$ $HADOOP_PREFIX/sbin/hadoop-daemons.sh --config $HADOOP_CONF_DIR --script hdfs stop datanode

作為 hdfs,如果 etc/hadoop/slaves 和 ssh 可信任訪問已經配置,那麼所有的 HDFS 程式都可以通過指令碼工具來關閉:

[hdfs]$ $HADOOP_PREFIX/sbin/stop-dfs.sh

作為 yarn,通過以下命令停止 ResourceManager:

[yarn]$ $HADOOP_YARN_HOME/sbin/yarn-daemon.sh --config $HADOOP_CONF_DIR stop resourcemanager

作為 yarn,執行一下指令碼停止 slave 機器上的 NodeManager :

[yarn]$ $HADOOP_YARN_HOME/sbin/yarn-daemons.sh --config $HADOOP_CONF_DIR stop nodemanager

作為 yarn,如果 etc/hadoop/slaves 和 ssh 可信任訪問已經配置,那麼所有的 YARN 程式都可以通過指令碼工具來關閉

[yarn]$ $HADOOP_PREFIX/sbin/stop-yarn.sh

作為 yarn,停止 WebAppProxy 伺服器。由於負載均衡有可能設定了多個:

[yarn]$ $HADOOP_YARN_HOME/sbin/yarn-daemon.sh --config $HADOOP_CONF_DIR stop proxyserver

作為 mapred,通過以下命令停止 MapReduce JobHistory Server :

[mapred]$ $HADOOP_PREFIX/sbin/mr-jobhistory-daemon.sh --config $HADOOP_CONF_DIR stop historyserver

8. Web 介面

當 Hadoop 啟動後,可以檢視如下 Web 介面:

守護進行 Web 介面 備註
NameNode http://nn_host:port/ 預設 HTTP 埠為 50070.
ResourceManager http://rm_host:port/ 預設 HTTP埠為 8088
MapReduce JobHistory Server http://jhs_host:port/ 預設 HTTP 埠為 19888

例子:詞頻統計 WordCount 程式

下面是 Hadoop 提供的詞頻統計 WordCount 程式 示例。執行執行改程式之前,請確保 HDFS 已經啟動。

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.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;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.mapreduce.Counter;
import org.apache.hadoop.util.GenericOptionsParser;
import org.apache.hadoop.util.StringUtils;

public class WordCount2 {

  public static class TokenizerMapper
       extends Mapper<Object, Text, Text, IntWritable>{

    static enum CountersEnum { INPUT_WORDS }

    private final static IntWritable one = new IntWritable(1);
    private Text word = new Text();

    private boolean caseSensitive;
    private Set<String> patternsToSkip = new HashSet<String>();

    private Configuration conf;
    private BufferedReader fis;

    @Override
    public void setup(Context context) throws IOException,
        InterruptedException {
      conf = context.getConfiguration();
      caseSensitive = conf.getBoolean("wordcount.case.sensitive", true);
      if (conf.getBoolean("wordcount.skip.patterns", true)) {
        URI[] patternsURIs = Job.getInstance(conf).getCacheFiles();
        for (URI patternsURI : patternsURIs) {
          Path patternsPath = new Path(patternsURI.getPath());
          String patternsFileName = patternsPath.getName().toString();
          parseSkipFile(patternsFileName);
        }
      }
    }

    private void parseSkipFile(String fileName) {
      try {
        fis = new BufferedReader(new FileReader(fileName));
        String pattern = null;
        while ((pattern = fis.readLine()) != null) {
          patternsToSkip.add(pattern);
        }
      } catch (IOException ioe) {
        System.err.println("Caught exception while parsing the cached file '"
            + StringUtils.stringifyException(ioe));
      }
    }

    @Override
    public void map(Object key, Text value, Context context
                    ) throws IOException, InterruptedException {
      String line = (caseSensitive) ?
          value.toString() : value.toString().toLowerCase();
      for (String pattern : patternsToSkip) {
        line = line.replaceAll(pattern, "");
      }
      StringTokenizer itr = new StringTokenizer(line);
      while (itr.hasMoreTokens()) {
        word.set(itr.nextToken());
        context.write(word, one);
        Counter counter = context.getCounter(CountersEnum.class.getName(),
            CountersEnum.INPUT_WORDS.toString());
        counter.increment(1);
      }
    }
  }

  public static class IntSumReducer
       extends Reducer<Text,IntWritable,Text,IntWritable> {
    private IntWritable result = new IntWritable();

    public void reduce(Text key, Iterable<IntWritable> values,
                       Context context
                       ) throws IOException, InterruptedException {
      int sum = 0;
      for (IntWritable val : values) {
        sum += val.get();
      }
      result.set(sum);
      context.write(key, result);
    }
  }

  public static void main(String[] args) throws Exception {
    Configuration conf = new Configuration();
    GenericOptionsParser optionParser = new GenericOptionsParser(conf, args);
    String[] remainingArgs = optionParser.getRemainingArgs();
    if (!(remainingArgs.length != 2 | | remainingArgs.length != 4)) {
      System.err.println("Usage: wordcount <in> <out> [-skip skipPatternFile]");
      System.exit(2);
    }
    Job job = Job.getInstance(conf, "word count");
    job.setJarByClass(WordCount2.class);
    job.setMapperClass(TokenizerMapper.class);
    job.setCombinerClass(IntSumReducer.class);
    job.setReducerClass(IntSumReducer.class);
    job.setOutputKeyClass(Text.class);
    job.setOutputValueClass(IntWritable.class);

    List<String> otherArgs = new ArrayList<String>();
    for (int i=0; i < remainingArgs.length; ++i) {
      if ("-skip".equals(remainingArgs[i])) {
        job.addCacheFile(new Path(remainingArgs[++i]).toUri());
        job.getConfiguration().setBoolean("wordcount.skip.patterns", true);
      } else {
        otherArgs.add(remainingArgs[i]);
      }
    }
    FileInputFormat.addInputPath(job, new Path(otherArgs.get(0)));
    FileOutputFormat.setOutputPath(job, new Path(otherArgs.get(1)));

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

待輸入的樣本檔案如下:

$ bin/hadoop fs -ls /user/joe/wordcount/input/
/user/joe/wordcount/input/file01
/user/joe/wordcount/input/file02

$ bin/hadoop fs -cat /user/joe/wordcount/input/file01
Hello World, Bye World!

$ bin/hadoop fs -cat /user/joe/wordcount/input/file02
Hello Hadoop, Goodbye to hadoop.

執行程式:

$ bin/hadoop jar wc.jar WordCount2 /user/joe/wordcount/input /user/joe/wordcount/output

輸出如下:

$ bin/hadoop fs -cat /user/joe/wordcount/output/part-r-00000
Bye 1
Goodbye 1
Hadoop, 1
Hello 2
World! 1
World, 1
hadoop. 1
to 1

通過 DistributedCache 來設定單詞過濾的策略:

$ bin/hadoop fs -cat /user/joe/wordcount/patterns.txt
\.
\,
\!
to

再次執行,這次增加了更多的選項:

$ bin/hadoop jar wc.jar WordCount2 -Dwordcount.case.sensitive=true /user/joe/wordcount/input /user/joe/wordcount/output -skip /user/joe/wordcount/patterns.txt

輸出如下:

$ bin/hadoop fs -cat /user/joe/wordcount/output/part-r-00000
Bye 1
Goodbye 1
Hadoop 1
Hello 2
World 2
hadoop 1

再次執行,這次去掉了大小寫敏感:

$ bin/hadoop jar wc.jar WordCount2 -Dwordcount.case.sensitive=false /user/joe/wordcount/input /user/joe/wordcount/output -skip /user/joe/wordcount/patterns.txt

輸出如下:

$ bin/hadoop fs -cat /user/joe/wordcount/output/part-r-00000
bye 1
goodbye 1
hadoop 2
hello 2
horld 2

相關文章