Hadoop

Hadoop

Hadoop是一個由Apache基金會所開發的分佈式系統基礎架構。

用戶可以在不瞭解分佈式底層細節的情況下,開發分佈式程序。充分利用集羣的威力進行高速運算和存儲。

Hadoop實現了一個分佈式文件系統(Hadoop Distributed File System),簡稱HDFS。HDFS有高容錯性的特點,並且設計用來部署在低廉的(low-cost)硬件上;而且它提供高吞吐量(high throughput)來訪問應用程序的數據,適合那些有着超大數據集(large data set)的應用程序。HDFS放寬了(relax)POSIX的要求,可以以流的形式訪問(streaming access)文件系統中的數據。

Hadoop的框架最核心的設計就是:HDFS和MapReduce。HDFS爲海量的數據提供了存儲,則MapReduce爲海量的數據提供了計算。

官網相關介紹:

What Is Apache Hadoop?

The Apache Hadoop project develops open-source software for reliable, scalable, distributed computing.

The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models. It is designed to scale up from single servers to thousands of machines, each offering local computation and storage. Rather than rely on hardware to deliver high-availability, the library itself is designed to detect and handle failures at the application layer, so delivering a highly-available service on top of a cluster of computers, each of which may be prone to failures.

The project includes these modules:

  • Hadoop Common: The common utilities that support the other Hadoop modules.

  • Hadoop Distributed File System (HDFS): A distributed file system that provides high-throughput access to application data.

  • Hadoop YARN: A framework for job scheduling and cluster resource management.

  • Hadoop MapReduce: A YARN-based system for parallel processing of large data sets.

Other Hadoop-related projects at Apache include:

  • Ambari: A web-based tool for provisioning, managing, and monitoring Apache Hadoop clusters which includes support for Hadoop HDFS, Hadoop MapReduce, Hive, HCatalog, HBase, ZooKeeper, Oozie, Pig and Sqoop. Ambari also provides a dashboard for viewing cluster health such as heatmaps and ability to view MapReduce, Pig and Hive applications visually alongwith features to diagnose their performance characteristics in a user-friendly manner.

  • Avro: A data serialization system.

  • Cassandra: A scalable multi-master database with no single points of failure.

  • Chukwa: A data collection system for managing large distributed systems.

  • HBase: A scalable, distributed database that supports structured data storage for large tables.

  • Hive: A data warehouse infrastructure that provides data summarization and ad hoc querying.

  • Mahout: A Scalable machine learning and data mining library.

  • Pig: A high-level data-flow language and execution framework for parallel computation.

  • Spark: A fast and general compute engine for Hadoop data. Spark provides a simple and expressive programming model that supports a wide range of applications, including ETL, machine learning, stream processing, and graph computation.

  • Tez: A generalized data-flow programming framework, built on Hadoop YARN, which provides a powerful and flexible engine to execute an arbitrary DAG of tasks to process data for both batch and interactive use-cases. Tez is being adopted by Hive, Pig and other frameworks in the Hadoop ecosystem, and also by other commercial software (e.g. ETL tools), to replace Hadoop MapReduce as the underlying execution engine.

  • ZooKeeper: A high-performance coordination service for distributed applications.


一、MapReduce理論基礎

每個MapReduce job都是Hadoop客戶端想要執行的一個工作單元,它一般由輸入數據、MapReduce程序和配置信息組成,而Hadoop會把每個job分隔成兩類任務(task):map任務和reduce任務。在Hadoop集羣中有兩類節點來執行兩類job進程的執行

1.1 大數據處理

任何基礎業務包含了收集、分析、監控、過濾、搜索或組織web內容的公司或組織都面臨着所謂的“大數據”問題:“web規模”處理即海量數據處理的代名詞。社交類網站的興起也使得這些組織面臨着另一個問題:用戶行爲數據分析,這涉及到通過日誌文件記錄用戶的對web頁面瀏覽、點擊、停留時長等,而後對日誌文件中的大量數據進行分析以支持進行合理、正確的商業決策。

那麼,大數據處理究竟意味着對多大規模的數據進行處理?一個簡單的例子:Google在2004年平均每天利用MapReduce處理100GB的數據,到2008年平均每天處理的數據已經達到20PB;2009年,Facebook的數據量達到2.5PB,且以每天15TB的速度在增長。PB級別的數據集正變得越來越常見,大數據時代的到來已然是不爭的事實,密集數據處理也正迅速成爲現實需求。

大數據問題的處理需要以與傳統數據處理方式所不同的方法去實現,這正是MapReduce思想得以大放光彩的核心所在。MapReduce在實現大數據處理上有着多個基礎理論思想的支撐,然而這些基礎理論甚至實現方法都未必是MapReduce所創,它們只是被MapReduce採用獨特的方式加以利用而已。

(1) 向外擴展(Scale out)而非向上擴展(Scale up):大數據的處理更適合採用大量低端商業服務器(scale out)而非少量高端服務器(scale up)。後者正是向上擴展的系統性能提升方式,它通常採用有着SMP架構的主機,然而有着大量的CPU插槽(成百上千個)及大量的共享內存(可以多達數百GB)的高端服務器非常昂貴,但其性能的增長卻非線性上升的,因此性價比很一般。而大量的低端商業服務器價格低廉、易於更換和伸縮等特性有效避免了向上擴展的敝端。

(2)假設故障很常見(Assume failures are common):在數據倉庫架構級別,故障是不可避免且非常普遍的。假設一款服務器出故障的平均概率爲1000天1次,那麼10000臺這種服務器每天出錯的可能性將達到10次。因此,大規模向外擴展的應用場景中,一個設計優良且具有容錯能力的服務必須能有效克服非常普遍的硬件故障所帶來的問題,即故障不能導致用戶應用層面的不一致性或非確定性。MapReduce編程模型能通過一系列機制如任務自動重啓等健壯地應付系統或硬件故障。

(3)將處理移向數據(Move processing to the data):傳統高性能計算應用中,超級計算機一般有着處理節點(processing node)和存儲節點(storage node)兩種角色,它們通過高容量的設備完成互聯。然而,大多數數據密集型的處理工作並不需要多麼強大的處理能力,於是把計算與存儲互相分開將使得網絡成爲系統性能瓶頸。爲了克服計算如此類的問題,MapReduce在其架構中將計算和存儲合併在了一起,並將數據處理工作直接放在數據存儲的位置完成,只不過這需要分佈式文件系統予以支撐。

(4)順序處理數據並避免隨機訪問(Process data sequentially and avoid random access):大數據處理通常意味着海量的數量難以全部載入內存,因而必須存儲在磁盤上。然而,機械式磁盤尋道操作的先天性缺陷使得隨機數據訪問成爲非常昂貴的操作,因此避免隨機數據訪問並以順序處理爲目的完成數據組織成爲亟待之需。固態磁盤雖然避免了機械磁盤的某此缺陷,然而其高昂的價格以及並沒有消除的隨機訪問問題仍然無法帶來性能上的飛躍發展。MapReduce則主要設計用來在海量數據集上完成批處理操作,即所有的計算被組織成較長的流式處理操作,以延遲換取較大的吞吐能力。

(5)向程序員隱藏系統級別的細節(Hide system-level details from the application developer):

(6)無縫擴展(Seamless scalability):

1.2 MapReduce和大數據問題

海量數據處理的核心思想無非是將一個較大的問題進行“分割包圍、逐個殲滅”。然而其難點和關鍵點在於如何將一個大的問題分分割成多個可以分別在不同的CPU上或不同的主機上進行處理的獨立小問題,而且這些獨立進行處理的小問題所產生的中間結果又該如何合併成最終結果並予以輸出。因此,看似簡單的化整爲零的處理思想卻不得不面臨如下的難題:

(1) 如何將大問題分割爲小任務?進一步地,如何將大問題分解爲可以並行處理的小任務?

(2) 如何將分解好的小任務派送給分佈式系統中的某主機且是較爲適合解決此問題的主機上的worker完成處理?

(3) 如何保證某worker獲取所需的數據?

(4) 如何協調不同worker之間進行同步?

(5) 如何將某worker的部分結果共享給其它需要此結果的worker?

(6) 如何在出現軟件或硬件故障時仍然能保證上述工作的順利進行?

在傳統的並行或分佈式編程模型中,程序員不得不顯式地解決上述的部分甚至是全部問題,而在共享內存編程中,程序員需要顯式地協調對共享數據結構的如互斥鎖的訪問、顯式地通過柵(barrier)等設備解決進程同步問題、並得時刻警惕着程序中可能出現的死鎖或競爭條件。雖然有些編程語言也或多或少地規避了讓程序員面對上述問題,但卻也避免不了將資源分配給各worker的問題。MapReduce的優勢之一便是有效地向程序員隱藏了這些問題。

1.3 函數式編譯語言

MapReduce是一種類似於Lisp或ML的函數式編程語言。函數式編程的核心特性之一是基於高階函數,即能夠接受其它函數作爲參數的函數完成編程。MapReduce有兩個常見地內置高階函數map和fold。

wKioL1hjcOWRrNMKAACqr9dNo2w085.png-wh_50

如圖所示,給定一個列表,map(接受一個參數)以函數f爲其參數並將其應用於列表中的所有元素;fold(接受兩個參數)以函數g和一個初始值作爲參數,然後將g應用於初始值和列表中的第一個元素,結果被放置於中間變量中。中間變量和第二個元素將作爲g函數下一次應用時的參數,而後如此操作直至將列表中的所有元素處理完畢後,fold會將最終處理結果保存至一箇中間變量中。

於是,基於上述過程,我們可以把map視作利用f函數將給定數據集完成形式轉換的操作,同樣地,fold就可以被看作利用g函數完成數據聚合的操作。我們就可以由此得知,各函數式程序在運行時彼此間是隔離的,因此,在map中將f函數應用於列表中每一個元素的操作可以並行進行,進一步地講,它們可以分佈於集羣中的不同節點上並行執行。然而,受限於數據的本地性,fold操作需要等到列表中的每一個元素都準備停當之後才能進行。幸運地是,現實生活中的應用程序並不要求g函數應用於列表中的所有元素,因此,列表中元素可以被分爲多個邏輯組,並將fold操作並行地應用在這些邏輯組上即可。由此,fold操作也可以以並行的方式高效完成。

MapReduce有兩個常見地內置高階函數map和reduce,其map就類似於上述過程中的map操作,reduce對應於上述過程中的fold操作。只不過,MapReduce的執行框架能自行協調map與reduce並將其應用於在商業服務器硬件平臺上並行處理海量數據。

更爲精確地說,MapReduce有三個相互關聯卻各不相同的概念。首先,MapReduce是一個如上所述的函數式編程語言。其次,MapReduce也是一個運行框架,它能夠協調運行基於MapReduce思想開發的程序。最後,MapReduce還可以被看作編程模型和執行框架的軟件實現,如Google的專有實現和另一個開源實現Hadoop等。

1.4 mapper和reducer

鍵值對兒(Key-value pair)是MapReduce的基礎數據結構。Key和Value可以是基礎類型數據,如整數、浮點數、字符串或未經加工的字節數據,也可以是任意形式的複雜數據類型。程序員可以自行定義所需的數據類型,也可藉助於Protocol Buffer、Thrift或Avro提供的便捷方式完成此類工作。

MapReduce算法設計的工作之一就是在給定數據集上定義“鍵-值”數據結構,比如在搜索引擎蒐集、存儲網頁類工作中,key可以使用URL來表示,而value則是網頁的內容。而在有些算法中,Key也可以是沒有任何實際意義的數據,其在數據處理過程中可被安全忽略。在MapReduce中,程序員需要基於如下方式定義mapper和reducer:

map: (k1,v1)-->[(k2,v20)]

reduce: (k2,[v2])-->[(k3,v3)]

其中[...]意味着其可以是一個列表。這些傳遞給MapReduce進行處理的數據存儲於分佈式文件上,mapper操作將應用於每一個傳遞過來的鍵-值對並生成一定數量的中間鍵值對(intermediate key-value),而後reduce操作將應用於這些中間鍵值對並輸出最終的鍵值對。然而,mapper操作和reducer操作之間還隱含着一個應用於中間鍵值對的“分組”操作,同一個鍵的鍵值對需要被歸類至同一組中併發送至同一個reducer,而傳送給每個reducer的分組中的鍵值對是基於鍵進行排序後的列表。reducer生成的結果將會保存至分佈式文件系統,並存儲爲一個或多個以r(即reducer號碼)結尾的文件,但mapper生成的中間鍵值對數據則不會被保存。

在Hadoop中,mapper和reducer是分別由MAP和REDUCE方法實現的對象。每個map任務(接收一個稱作input split的鍵值對列表)都被初始化一個mapper對象,並會由執行框架爲每個輸入的鍵值對調用一次其map方法。程序員可以配置啓動的map任務個數,但其真正啓動的數目則由執行框架根據數據的物理分佈最終給定。類似地,每個reduce任務由REDUCE方法初始化爲一個reduce對象,並會由執行框架爲其接受的每個中間鍵值對調用一次REDUCE方法,所不同的是,程序員可以明確限定啓動的reduce任務的個數。

mapper和reducer可以直接在各自接收的數據上執行所需要的操作,然而,當使用到外部資源時,多個mapper或reducer之間可能會產生資源競爭,這勢必導致其性能下降,因此,程序員必須關注其所用資源的競爭條件並加入適當處理。其次,mapper輸出的中間鍵值對與接受的鍵值對可以是不同的數據類型,類似地,reducer輸出的鍵值對與其接收的中間鍵值對也可以是不同的數據類型,這可能會給編程過程及程序運行中的故障排除帶來困難,但這也正是MapReduce強大功能的體現之一。

除了常規的兩階段MapReduce處理流外,其還有一些變化形式。比如將mapper輸出的結果直接保存至磁盤中(每個mapper對應一個文件)的沒有reducer的MapReduce作業,不過僅有reducer而沒有mapper的作業是不允許的。不過,就算用不着reducer處理具體的操作,利用reducer將mapper的輸出結果進行重新分組和排序後進行輸出也能以另一種形式提供的完整MapReduce模式。

MapReduce作業一般是通過HDFS讀取和保存數據,但它也可以使用其它滿足MapReduce應用的數據源或數據存儲,比如Google的MapReduce實現中使用了Bigtable來完成數據的讀入或輸出。BigTable屬於非關係的數據庫,它是一個稀疏的、分佈式的、持久化存儲的多維度排序Map,其設計目的是可靠的處理PB級別的數據,並且能夠部署到上千臺機器上。在Hadoop中有一個類似的實現HBase可用於爲MapReduce提供數據源和數據存儲。

1.5 Hadoop運行框架

MapReduce程序也稱作爲MapReduce作業,一般由mapper代碼、reducer代碼以及其配置參數(如從哪兒讀入數據,以及輸出數據的保存位置)組成。準備好的作業可通過JobTracker(作業提交節點)進行提交,然後由運行框架負責完成後續的其它任務。這些任務主要包括如下幾個方面。

(1) 調度

每個MapReduce作業都會劃分爲多個稱作任務(task)的較小單元,而較大的作業劃分的任務數量也可能會超出整個集羣可運行的任務數,此時就需要調度器程序維護一個任務隊列並能夠追蹤正在運行態任務的相關進程,以便讓隊列中處於等待狀態的任務派送至某轉爲可用狀態的節點運行。此外,調度器還要負責分屬於不同作業的任務協調工作。

對於一個運行中的作業來說,只有所用的map任務都完成以後才能將中間數據分組、排序後發往reduce作業,因此,map階段的完成時間取決於其最慢的一個作業的完成時間。類似的,reduce階段的最後一個任務執行結束,其最終結果才爲可用。因此,MapReduce作業完成速度則由兩個階段各自任務中的掉隊者決定,最壞的情況下,這可能會導致作業長時間得不到完成。出於優化執行的角度,Hadoop和Google MapReduce實現了推測執行(Speculative execution)機制,即同一個任務會在不同的主機上啓動多個執行副本,運行框架從其最快執行的任務中取得返回結果。不過,推測執行並不能消除其它的滯後場景,比如中間鍵值對數據的分發速度等。

(2) 數據和代碼的協同工作(data/code co-location)

術語“數據分佈”可能會帶來誤導,因爲MapReduce盡力保證的機制是將要執行的代碼送至數據所在的節點執行,因爲代碼的數據量通常要遠小於要處理的數據本身。當然,MapReduce並不能消除數據傳送,比如在某任務要處理的數據所在的節點已經啓動很多任務時,此任務將不得不在其它可用節點運行。此時,考慮到同一個機架內的服務器有着較充裕的網絡帶寬,一個較優選擇是從數據節點同一個機架內挑選一個節點來執行此任務。

(3) 同步(Synchronization)

異步環境下的一組併發進程因直接制約而互相發送消息而進行互相合作、互相等待,使得各進程按一定的速度執行的過程稱爲進程間同步,其可分爲進程同步(或者線程同步)和數據同步。就編程方法來說,保持進程間同步的主要方法有內存屏障(Memory barrier),互斥鎖(Mutex),信號量(Semaphore)和鎖(Lock),管程(Monitor),消息(Message),管道(Pipe)等。MapReduce是通過在map階段的進程與reduce階段的進程之間實施隔離來完成進程同步的,即map階段的所有任務都完成後對其產生的中間鍵值對根據鍵完成分組、排序後通過網絡發往各reducer方可開始reduce階段的任務,因此這個過程也稱爲“shuffle and sort”。

(4) 錯誤和故障處理(Error and fault handling)

MapReduce運行框架本身就是設計用來容易發生故障的商用服務器上了,因此,其必須有着良好的容錯能力。在任何類別的硬件故障發生時,MapReduce運行框架均可自行將運行在相關節點的任務在一個新挑選出的節點上重新啓動。同樣,在任何程序發生故障時,運行框架也要能夠捕獲異常、記錄異常並自動完成從異常中恢復。另外,在一個較大規模的集羣中,其它任何超出程序員理解能力的故障發生時,MapReduce運行框架也要能夠安全挺過。

1.6 partitioner和combiner

除了前述的內容中的組成部分,MapReduce還有着另外兩個組件:partiontioner和combiner。

Partitioner負責分割中間鍵值對數據的鍵空間(即前面所謂的“分組”),並將中間分割後的中間鍵值對發往對應的reducer,也即partitioner負責完成爲一箇中間鍵值對指派一個reducer。最簡單的partitioner實現是將鍵的hash碼對reducer進行取餘計算,並將其發往餘數對應編號的reducer,這可以盡力保證每個reducer得到的鍵值對數目大體上是相同的。不過,由於partitioner僅考慮鍵而不考慮“值”,因此,發往每個reducer的鍵值對在鍵數目上的近似未必意味着數據量的近似。

Combiner是MapReduce的一種優化機制,它的主要功能是在“shuffle and sort”之前先在本地將中間鍵值對進行聚合,以減少在網絡上發送的中間鍵值對數據量。因此可以把combiner視作在“shuffle and sort”階段之前對mapper的輸出結果所進行聚合操作的“mini-reducer”。在實現中,各combiner之間的操作是隔離的,因此,它不會涉及到其它mapper的數據結果。需要注意的是,就算是某combiner可以有機會處理某鍵相關的所有中間數據,也不能將其視作reducer的替代品,因爲combiner輸出的鍵值對類型必須要與mapper輸出的鍵值對類型相同。無論如何,combiner的恰當應用將有機會有效提高作業的性能。

2.1 HDFS的設計理念

HDFS專爲存儲大文件而設計,可運行於普通的商業服務器上,基於流式數據訪問模型完成數據存取。HDFS將所有文件的元數據存儲於名稱節點(NameNode)的內存中,能夠利用分佈式特性高效地管理“大”文件(GB級別甚至更大的文件),對於有着海量小文件的應用場景則會給名稱節點帶去巨大壓力並使得其成爲系統性能瓶頸。再者,HDFS爲MapReduce的計算框架而設計,存儲下來數據主要用於後續的處理分析,其訪問模型爲“一次寫入、多次讀取”;因此,數據在HDFS中存儲完成後,僅能在文件尾部附加新數據,而不能對文件進行修改。另外,HDFS專爲了高效地傳輸大文件進行了優化,其爲了完成此目標,在“低延遲”特性上做出了很大讓步,因此,其不適用於較小訪問延遲的應用。

2.2 HDFS架構

2.2.1 HDFS數據塊

與傳統文件系統一樣,HDFS也在“塊(block)”級別存取文件,所不同的是,傳統文件系統數據塊一般較小(1KB、2KB或4KB等),HDFS的數據塊大小默認爲64MB,甚至可以使用128MB或256MB級別的數據塊。HDFS使用塊抽象層管理文件,可以實現將分塊分爲多個邏輯部分後分佈於多個存儲節點,也能夠有效簡化存儲子系統。而對於存儲節點來說,較大的塊可以減少磁盤的尋道次數,進而提升I/O性能。

2.2.2 名稱節點(NameNode)和數據節點(DataNode)

HDFS集羣中節點的工作模型爲“master-worker”:其包含一個名稱節點(master)和多個數據節點(worker)。

名稱節點負責管理HDFS的名稱空間,即以樹狀結構組織的目錄及文件的元數據信息,這些信息持久存儲於名稱節點本地磁盤上並保存爲名稱空間鏡像(namespace image)和編輯日誌(edit log)兩個文件。名稱節點並不存儲數據塊,它僅需要知道每個文件對應數據塊的存儲位置,即真正存儲了數據塊的數據節點。然而,名稱節點並不會持久存儲數據塊所與其存儲位置的對應信息,因爲這些信息是在HDFS集羣啓動由名稱節點根據各數據節點發來的信息進行重建而來。這個重建過程被稱爲HDFS的安全模式。數據節點的主要任務包括根據名稱節點或客戶的要求完成存儲或讀取數據塊,並週期性地將其保存的數據塊相關信息報告給名稱節點。

默認情況下,HDFS會在集羣中爲每個數據塊存儲三個副本以確保數據的可靠性、可用性及性能表現。在一個大規模集羣中,這三個副本一般會保存至不同機架中的數據節點上以應付兩種常見的故障:單數據節點故障和導致某機架上的所有主機離線的網絡故障。另外,如前面MapReduce運行模型中所述,爲數據塊保存多個副本也有利於MapReduce在作業執行過程中透明地處理節點故障等,併爲MapReduce中作業協同處理以提升性能提供了現實支撐。名稱節點會根據數據節點的週期性報告來檢查每個數據塊的副本數是否符合要求,低於配置個數要求的將會對其進行補足,而多出的將會被丟棄。

HDFS提供了POSIX網絡的訪問接口,所有的數據操作對客戶端程序都是透明的。當客戶端程序需要訪問HDFS中的數據時,它首先基於TCP/IP協議與名稱節點監聽的TCP端口建立連接,接着通過客戶端協議(Client Protocol)發起讀取文件的請求,而後名稱節點根據用戶請求返回相關文件的塊標識符(blockid)及存儲了此數據塊的數據節點。接下來客戶端向對應的數據節點監聽的端口發起請求並取回所需要數據塊。當需要存儲文件並寫數據時,客戶端程序首先會向名稱節點發起名稱空間更新請求,名稱節點檢查用戶的訪問權限及文件是否已經存在,如果沒有問題,名稱空間會挑選一個合適的數據節點分配一個空閒數據塊給客戶端程序。客戶端程序直接將要存儲的數據發往對應的數據節點,在完成存儲後,數據節點將根據名稱節點的指示將數據塊複製多個副本至其它節點。

2.2.3 名稱節點的可用性

由前一節所述的過程可以得知,名稱節點的宕機將會導致HDFS文件系統中的所有數據變爲不可用,而如果名稱節點上的名稱空間鏡像文件或編輯日誌文件損壞的話,整個HDFS甚至將無從重建,所有數據都會丟失。因此,出於數據可用性、可靠性等目的,必須提供額外的機制以確保此類故障不會發生,Hadoop爲此提供了兩種解決方案。

最簡單的方式是將名稱節點上的持久元數據信息實時存儲多個副本於不同的存儲設備中。Hadoop的名稱節點可以通過屬性配置使用多個不同的名稱空間存儲設備,而名稱節點對多個設備的寫入操作是同步的。當名稱節點故障時,可在一臺新的物理主機上加載一份可用的名稱空間鏡像副本和編輯日誌副本完成名稱空間的重建。然而,根據編輯日誌的大小及集羣規模,這個重建過程可能需要很長時間。

另一種方式是提供第二名稱節點(Secondary NameNode)。第二名稱節點並不真正扮演名稱節點角色,它的主要任務是週期性地將編輯日誌合併至名稱空間鏡像文件中以免編輯日誌變得過大。它運行在一個獨立的物理主機上,並需要跟名稱節點同樣大的內存資源來完成文件合併。另外,它還保存一份名稱空間鏡像的副本。然而,根據其工作機制可知,第二名稱節點要滯後於主節點,因此名稱節點故障時,部分數據丟失仍然不可避免。

儘管上述兩種機制可以最大程序上避免數據丟失,但其並不具有高可用的特性,名稱節點依然是一個單點故障,因爲其宕機後,所有的數據將不能夠被訪問,進而所有依賴於此HDFS運行的MapReduce作業也將中止。就算是備份了名稱空間鏡像和編輯日誌,在一個新的主機上重建名稱節點並完成接收來自各數據節點的塊信息報告也需要很長的時間才能完成。在有些應用環境中,這可能是無法接受的,爲此,Hadoop 0.23引入了名稱節點的高可用機制——設置兩個名稱節點工作於“主備”模型,主節點故障時,其所有服務將立即轉移至備用節點。進一步信息請參考官方手冊。

在大規模的HDFS集羣中,爲了避免名稱節點成爲系統瓶頸,在Hadoop 0.23版本中引入了HDFS聯邦(HDFS Federation)機制。HDFS聯邦中,每個名稱節點管理一個由名稱空間元數據和包含了所有塊相關信息的塊池組成名稱空間卷(namespace volume),各名稱節點上的名稱空間卷是互相隔離的,因此,一個名稱節點的損壞並不影響其它名稱節點繼續提供服務。進一步信息請參考官方手冊。

二、安裝配置hadoop:

2.1 安裝前的準備工作

本示例所演示的過程基於RHEL 5.8(32bit)平臺,用到的應用程序如下所示。

JDK: jdk-7u5-linux-i586.rpm

Hadoop:hadoop-0.20.2-cdh3u5.tar.gz

安全起見,運行Hadoop需要以普通用戶的身份進行,因此,接下來先建立運行hadoop進程的用戶hadoop並給其設定密碼。

# useradd hadoop
# echo "password" | passwd --stdin hadoop

而後配置hadoop用戶能夠以基於密鑰的驗正方式登錄本地主機,以便Hadoop可遠程啓動各節點上的Hadoop進程並執行監控等額外的管理工作。

[root@master ~]# su - hadoop
[hadoop@master ~]$ ssh-keygen -t rsa -P '' 
[hadoop@master ~]$ ssh-copy-id -i .ssh/id_rsa.pub hadoop@localhost

2.2 安裝JDK

Hadoop依賴於1.6 update 8或更新版本的Java環境。本文采用的jdk是rpm格式的安裝包,在oracle官方的下載頁面中即可找到合適的版本。其安裝過程非常簡單,使用類似如下命令即可。

# rpm -ivh jdk-7u5-linux-i586.rpm

Hadoop運行時需要能訪問到如前安裝的Java環境,這可以通過將其二進制程序(/usr/java/latest)所在的目錄添加至PATH環境變量的路徑中實現,也可以通過設定hadoop-env.sh腳本來進行。這裏採用前一種方式,編輯/etc/profile.d/java.sh,在文件中添加如下內容:

JAVA_HOME=/usr/java/latest/
PATH=$JAVA_HOME/bin:$PATH
export JAVA_HOME PATH

切換至hadoop用戶,並執行如下命令測試jdk環境配置是否就緒。

# su - hadoop
$ java -version
java version "1.7.0_05"
Java(TM) SE Runtime Environment (build 1.7.0_05-b05)
Java HotSpot(TM) Client VM (build 23.1-b03, mixed mode, sharing)

2.3 hadoop安裝配置

2.3.1 安裝:

# tar xf hadoop-0.20.2-cdh3u5.tar.gz -C /usr/local
# chown -R hadoop:hadoop /usr/local/hadoop-0.20.2-cdh3u5
# ln -sv /usr/local/hadoop-0.20.2-cdh3u5 /usr/local/hadoop

然後編輯/etc/profile.d/hadoop.sh,設定HADOOP_HOME環境變量的值爲hadoop的解壓目錄,並讓其永久有效。編輯/etc/profile,添加如下內容:

HADOOP_BASE=/usr/local/hadoop
PATH=$HADOOP_BASE/bin:$PATH
export HADOOP_BASE PATH

切換至hadoop用戶,並執行如下命令測試hadoop是否就緒。

# hadoop version
Hadoop 0.20.2-cdh3u5
Subversion git://ubuntu-slave02/var/lib/jenkins/workspace/CDH3u5-Full-RC/build/cdh3/hadoop20/0.20.2-cdh3u5/source -r 30233064aaf5f2492bc687d61d72956876102109
Compiled by jenkins on Fri Oct  5 17:21:34 PDT 2012
From source with checksum de1770d69aa93107a133657faa8ef467

2.3.2 Hadoop的配置文件:

hadoop-env.sh: 用於定義hadoop運行環境相關的配置信息,比如配置JAVA_HOME環境變量、爲hadoop的JVM指定特定的選項、指定日誌文件所在的目錄路徑以及master和slave文件的位置等;

core-site.xml: 用於定義系統級別的參數,如HDFS URL、Hadoop的臨時目錄以及用於rack-aware集羣中的配置文件的配置等,此中的參數定義會覆蓋core-default.xml文件中的默認配置;

hdfs-site.xml: HDFS的相關設定,如文件副本的個數、塊大小及是否使用強制權限等,此中的參數定義會覆蓋hdfs-default.xml文件中的默認配置;

mapred-site.xml:HDFS的相關設定,如reduce任務的默認個數、任務所能夠使用內存的默認上下限等,此中的參數定義會覆蓋mapred-default.xml文件中的默認配置;

masters: hadoop的secondary-masters主機列表,當啓動Hadoop時,其會在當前主機上啓動NameNode和JobTracker,然後通過SSH連接此文件中的主機以作爲備用NameNode; 

slaves:Hadoop集羣的slave主機列表,master啓動時會通過SSH連接至此列表中的所有主機併爲其啓動DataNode和taskTracker進程;

2.3.3 Hadoop的分佈式模型

Hadoop通常有三種運行模式:本地(獨立)模式、僞分佈式(Pseudo-distributed)模式和完全分佈式(Fully distributed)模式。

安裝完成後,Hadoop的默認配置即爲本地模式,此時Hadoop使用本地文件系統而非分佈式文件系統,而且其也不會啓動任何Hadoop守護進程,Map和Reduce任務都作爲同一進程的不同部分來執行。因此,本地模式下的Hadoop僅運行於本機。此種模式僅用於開發或調試MapReduce應用程序但卻避免了複雜的後續操作。

僞分佈式模式下,Hadoop將所有進程運行於同一臺主機上,但此時Hadoop將使用分佈式文件系統,而且各jobs也是由JobTracker服務管理的獨立進程。同時,由於僞分佈式的Hadoop集羣只有一個節點,因此HDFS的塊複製將限制爲單個副本,其secondary-master和slave也都將運行於本地主機。此種模式除了並非真正意義的分佈式之外,其程序執行邏輯完全類似於完全分佈式,因此,常用於開發人員測試程序執行。

要真正發揮Hadoop的威力,就得使用完全分佈式模式。由於ZooKeeper實現高可用等依賴於奇數法定數目(an odd-numbered quorum),因此,完全分佈式環境需要至少三個節點。

2.3.4 配置Hadoop的僞分佈式模式

傳統上使用的hadoop-site.xml文件已經過時,現在分別使用core-site.xml、mapred-site.xml和hdfs-site.xml來取代core-default.xml、mapred-default.xml和 hdfs-default.xml中的默認配置。hadoop爲這些文件提供了模板,其關於xml文檔文件格式定義的部分及<configure></configure>已經存在,此時所需要做的僅是在其中添加相應的配置即可。

2.3.4.1 編輯conf/core-site.xml,配置Hadoop的核心屬性

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
  <property>
    <name>hadoop.tmp.dir</name>
    <value>/hadoop/temp</value>
  </property>
  
  <property>
    <name>fs.default.name</name>
    <value>hdfs://localhost:8020</value>
  </property>  
</configuration>

上面示例中hadoop.tmp.dir屬性用於定義Hadoop的臨時目錄,其默認爲/tmp/hadoop-${username}。HDFS進程的許多目錄默認都在此目錄中,本示例將其定義到了/hadoop/temp目錄,需要注意的是,要保證運行Hadoop進程的用戶對其具有全部訪問權限。fs.default.name屬性用於定義HDFS的名稱節點和其默認的文件系統,其值是一個URI,即NameNode的RPC服務器監聽的地址(可以是主機名)和端口(默認爲8020)。其默認值爲file:///,即本地文件系統。

2.3.4.2 編輯conf/mapred-site.xml,定義MapReduce

運行MapReduce需要爲其指定一個主機作爲JobTracker節點,在一個小規模的Hadoop集羣中,它通常跟NameNode運行於同一物理主機。可以通過mapred.job.trakcer屬性定義JobTracker監聽的地址(或主機名)和端口(默認爲8021),與前面的fs.default.name屬性的值不同的是,這不是一個URI,而僅一個“主機-端口”組合。

在MapReduce作業運行過程中,中間數據(intermediate data)和工作文件保存於本地臨時文件中。根據運行的MapReduce作業不同,這些數據文件可能會非常大,因此,應該通過mapred.local.dir屬性爲其指定一個有着足夠空間的本地文件系統路徑,其默認值爲${hadoop.tmp.dir}/mapred/local。mapred.job.tracker可以接受多個以逗號分隔路徑列表作爲其值,並會以輪流的方式將數據分散存儲在這些文件系統上,因此指定位於不同磁盤上的多個文件系統路徑可以分散數據I/O。

另外,MapReduce使用分佈式文件系統爲各TaskTracker保存共享數據,這可以通過mapred.system.dir屬性進行定義,其默認值爲${hadoop.tmp.dir}/mapred/system。下面給出了一個較簡單的mapred-site.xml文件示例。

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
  <property>
    <name>mapred.job.tracker</name>
    <value>localhost:8021</value>
  </property>
</configuration>

2.3.4.3 編輯conf/hdfs-site.xml,定義hdfs的屬性

HDFS進程有許多屬性可以定義其工作路,如dfs.name.dir屬性定義的HDFS元數據持久存儲路徑默認爲${hadoop.tmp.dir}/dfs/name、dfs.data.dir屬性定義的DataNode用於存儲數據塊的目錄路徑默認爲${hadoop.tmp.dir}/dfs/data、fs.checkpoint.dir屬性定義的SecondaryNameNode用於存儲檢查點文件的目錄默認爲${hadoop.tmp.dir}/dfs/namesecondary。

爲了數據可用性及冗餘的目的,HDFS會在多個節點上保存同一個數據塊的多個副本,其默認爲3個。而只有一個節點的僞分佈式環境中其僅用保存一個副本即可,這可以通過dfs.replication屬性進行定義。如下所示的內容即可作爲最簡單的hdfs-site.xml配置文件。

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
  <property>
    <name>dfs.replication</name>
    <value>1</value>
  </property>
</configuration>

2.3.4.4 格式化名稱節點

以hadoop用戶運行如下命令

$ hadoop namenode -format

其執行後會顯示爲類似如下內容:

12/12/06 22:16:02 INFO namenode.NameNode: STARTUP_MSG: 
/************************************************************
STARTUP_MSG: Starting NameNode
STARTUP_MSG:   host = localhost.localdomain/127.0.0.1
STARTUP_MSG:   args = [-format]
STARTUP_MSG:   version = 0.20.2-cdh3u5
STARTUP_MSG:   build = git://ubuntu-slave02/var/lib/jenkins/workspace/CDH3u5-Full-RC/build/cdh3/hadoop20/0.20.2-cdh3u5/source -r 30233064aaf5f2492bc687d61d72956876102109; compiled by 'jenkins' on Fri Oct  5 17:21:34 PDT 2012
************************************************************/
12/12/06 22:16:03 INFO util.GSet: VM type       = 32-bit
12/12/06 22:16:03 INFO util.GSet: 2% max memory = 19.33375 MB
12/12/06 22:16:03 INFO util.GSet: capacity      = 2^22 = 4194304 entries
12/12/06 22:16:03 INFO util.GSet: recommended=4194304, actual=4194304
12/12/06 22:16:03 INFO namenode.FSNamesystem: fsOwner=hadoop (auth:SIMPLE)
12/12/06 22:16:04 INFO namenode.FSNamesystem: supergroup=supergroup
12/12/06 22:16:04 INFO namenode.FSNamesystem: isPermissionEnabled=true
12/12/06 22:16:04 INFO namenode.FSNamesystem: dfs.block.invalidate.limit=1000
12/12/06 22:16:04 INFO namenode.FSNamesystem: isAccessTokenEnabled=false accessKeyUpdateInterval=0 min(s), accessTokenLifetime=0 min(s)
12/12/06 22:16:04 INFO common.Storage: Image file of size 112 saved in 0 seconds.
12/12/06 22:16:05 INFO common.Storage: Storage directory /hadoop/temp/dfs/name has been successfully formatted.
12/12/06 22:16:05 INFO namenode.NameNode: SHUTDOWN_MSG: 
/************************************************************
SHUTDOWN_MSG: Shutting down NameNode at localhost.localdomain/127.0.0.1
************************************************************/

其中的“Storage directory /hadoop/temp/dfs/name has been successfully formatted”一行信息表明對應的存儲已經格式化成功。

2.3.4.5 啓動hadoop

Hadoop提供了2個腳本start-dfs.shstart-mapred.sh,分別用於啓動hdfs相關的進程和mapred相關的進程。事實上,爲了使用的便捷性,在NameNode和JobTracker運行於同一主機的場景中,Hadoop還專門提供了腳本start-all.sh腳本來自動執行前述兩個腳本。

$ /usr/local/hadoop/bin/start-all.sh

其會輸出類似如下內容:

starting namenode, logging to /usr/local/hadoop/logs/hadoop-hadoop-namenode-localhost.localdomain.out
localhost: starting datanode, logging to /usr/local/hadoop/logs/hadoop-hadoop-datanode-localhost.localdomain.out
localhost: starting secondarynamenode, logging to /usr/local/hadoop/logs/hadoop-hadoop-secondarynamenode-localhost.localdomain.out
starting jobtracker, logging to /usr/local/hadoop/logs/hadoop-hadoop-jobtracker-localhost.localdomain.out
localhost: starting tasktracker, logging to /usr/local/hadoop/logs/hadoop-hadoop-tasktracker-localhost.localdomain.out

運行jps命令查看正在運行的Hadoop進程

$ jps | grep -iv "jps"
29326 DataNode
29478 SecondaryNameNode
29685 TaskTracker
29208 NameNode
29563 JobTracker

2.3.4.6 Hadoop進程監聽的地址和端口

Hadoop啓動時會運行兩個服務器進程,一個爲用於Hadoop各進程之間進行通信的RPC服務器,另一個是提供了便於管理員查看Hadoop集羣各進程相關信息頁面的HTTP服務器。

用於定義各RPC服務器所監聽的地址和端口的屬性有如下幾個:

fs.default.name:定義HDFS的NameNode用於提供URI所監聽的地址和端口,默認端口爲8020;

dfs.datanode.ipc.address:DataNode上IPC服務器監聽的地址和端口,默認爲0.0.0.0:50020;

mapred.job.tracker:JobTracker的PRC服務器所監聽的地址和端口,默認端口爲8021;

mapred.task.tracker.report.address:TaskTracker的RPC服務器監聽的地址和端口;TaskTracker的子JVM使用此端口與TaskTracker進行通信,它僅需要監聽在本地迴環地址127.0.0.1上,因此可以使用任何端口;只有在當本地沒有迴環接口時才需要修改此屬性的值;

除了RPC服務器之外,DataNode還會運行一個TCP/IP服務器用於數據塊傳輸,其監聽的地址和端口可以通過dfs.datanode.address屬性進行定義,默認爲0.0.0.0:50010。

可用於定義各HTTP服務器的屬性有如下幾個:

mapred.job.tracker.http.addrss:JobTracker的HTTP服務器地址和端口,默認爲0.0.0.0:50030;

mapred.task.tracker.http.address:TaskTracker的HTTP服務器地址和端口,默認爲0.0.0.0:50060;

dfs.http.address:NameNode的HTTP服務器地址和端口,默認爲0.0.0.0:50070;

dfs.datanode.http.address:DataNode的HTTP服務器地址和端口,默認爲0.0.0.0:50075;

dfs.secondary.http.address:SecondaryNameNode的HTTP服務器地址和端口,默認爲0.0.0.0:50090;

上述的HTTP服務器均可以通過瀏覽器直接訪問以獲取對應進程的相關信息。

下面的命令可以查看jvm監聽的端口。 

$ netstat -tnlp | grep "java"
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
tcp        0      0 0.0.0.0:50020               0.0.0.0:*                   LISTEN      29326/java          
tcp        0      0 0.0.0.0:52805               0.0.0.0:*                   LISTEN      29208/java          
tcp        0      0 0.0.0.0:50090               0.0.0.0:*                   LISTEN      29478/java          
tcp        0      0 0.0.0.0:50060               0.0.0.0:*                   LISTEN      29685/java          
tcp        0      0 0.0.0.0:50030               0.0.0.0:*                   LISTEN      29563/java          
tcp        0      0 0.0.0.0:51664               0.0.0.0:*                   LISTEN      29478/java          
tcp        0      0 0.0.0.0:54898               0.0.0.0:*                   LISTEN      29326/java          
tcp        0      0 0.0.0.0:55475               0.0.0.0:*                   LISTEN      29563/java          
tcp        0      0 127.0.0.1:8020              0.0.0.0:*                   LISTEN      29208/java          
tcp        0      0 127.0.0.1:44949             0.0.0.0:*                   LISTEN      29685/java          
tcp        0      0 127.0.0.1:8021              0.0.0.0:*                   LISTEN      29563/java          
tcp        0      0 0.0.0.0:50070               0.0.0.0:*                   LISTEN      29208/java          
tcp        0      0 0.0.0.0:50010               0.0.0.0:*                   LISTEN      29326/java          
tcp        0      0 0.0.0.0:50075               0.0.0.0:*                   LISTEN      29326/java

2.4 Hadoop命令

hadoop有很多子命令,用於完成不同的功能,這個可以通過如下命令查看。

$ hadoop

其中的fs子命令用於進行跟文件系統相關的多種操作,如創建目錄、複製文件或目錄等,其具體的使用幫助可以使用如下命令獲得。

$ hadoop fs -help

hadoop的fs命令能同時跟本地文件系統和HDFS交互,甚至可以跟Amazon的S3進行交互。其使用URI格式路徑引用文件路徑,完全的URI格式類似schema://authority/path,其中schema類似於協議,這裏可以使用hdfs或file,分別用於引用 HDFS文件或本地文件系統中的文件。而對於HDFS來說,authority是指Namenode主機,path是指具體的文件路徑。例如,在僞文件系統模式中,HDFS運行於本機的8020端口,因此hdfs://localhost:8020/user/hadoop/test.txt就是一個完整意義上的URI。事實上,在使用中,也可以省略URI中的schema://authority部分,此時其使用配置文件中默認名稱段的定義,如我們前面定義的類似如下段的配置信息:

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

在fs命令用於實現在本地文件系統和HDFS之間傳遞文件時,可以使用-get(從HDFS中複製文件至本地文件系統)或-put(將本地文件複製到HDFS中)命令實現,而fs會根據使用的命令來判斷哪個是本地文件系統路徑,哪個是HDFS文件系統路徑,如將本地的/etc/issue複製到HDFS中存放至當前hadoop用戶的目錄中,則可使用如下命令:

$ hadoop fs -put /etc/issue  hdfs://localhost:9000/user/hadoop/

或使用命令

$ hadoop fs -put /etc/issue  /user/hadoop/

複製的結果可以使用如下命令查看:

$ hadoop fs -ls
Found 1 items
-rw-r--r--   1 hadoop supergroup         74 2012-09-20 23:03 /user/hadoop/issue

hadoop對文件系統的管理是通過java類來實現的,而其用於文件系統管理的類有多種,分別用於通過不同的方式訪問不同的文件系統。hdfs和file是schema中常見的兩種方式。

hadoop常用的命令行命令及其用法列表請參見如下鏈接:

HDFS命令:http://hadoop.apache.org/common/docs/r1.0.0/file_system_shell.html

MapReduce的job命令:http://hadoop.apache.org/common/docs/r1.0.0/commands_manual.html#job

2.5 測試Hadoop

Hadoop提供了MapReduce編程框架,其並行處理能力的發揮需要通過開發Map及Reduce程序實現。爲了便於系統測試,Hadoop提供了一個單詞統計的應用程序算法樣例,其位於Hadoop安裝目錄下名稱類似hadoop-examples-*.jar的文件中。除了單詞統計,這個jar文件還包含了分佈式運行的grep等功能的實現,這可以通過如下命令查看。

$ hadoop jar /usr/local/hadoop/hadoop-examples-0.20.2-cdh3u5.jar 
An example program must be given as the first argument.
Valid program names are:
  aggregatewordcount: An Aggregate based map/reduce program that counts the words in the input files.
  aggregatewordhist: An Aggregate based map/reduce program that computes the histogram of the words in the input files.
  dbcount: An example job that count the pageview counts from a database.
  grep: A map/reduce program that counts the matches of a regex in the input.
  join: A job that effects a join over sorted, equally partitioned datasets
  multifilewc: A job that counts words from several files.
  pentomino: A map/reduce tile laying program to find solutions to pentomino problems.
  pi: A map/reduce program that estimates Pi using monte-carlo method.
  randomtextwriter: A map/reduce program that writes 10GB of random textual data per node.
  randomwriter: A map/reduce program that writes 10GB of random data per node.
  secondarysort: An example defining a secondary sort to the reduce.
  sleep: A job that sleeps at each map and reduce task.
  sort: A map/reduce program that sorts the data written by the random writer.
  sudoku: A sudoku solver.
  teragen: Generate data for the terasort
  terasort: Run the terasort
  teravalidate: Checking results of terasort
  wordcount: A map/reduce program that counts the words in the input files.

接下來的過程來演示在HDFS的wc-in目錄中存放兩個測試文件,而後運行wordcount程序實現對這兩個測試文件中各單詞出現次數進行統計的實現過程。首先創建wc-in目錄,並複製文件至HDFS文件系統中。

$ hadoop fs -mkdir wc-in
$ hadoop fs -put /etc/rc.d/init.d/functions /etc/profile wc-in

接下來啓動分佈式任務,其中的wc-out爲reduce任務執行結果文件所在的目錄,此目標要求事先不能存在,否則運行將會報錯。

$ hadoop jar /usr/local/hadoop/hadoop-example-*.jar wordcount wc-in wc-out

輸出結果類似如下內容:

12/12/06 23:11:38 INFO input.FileInputFormat: Total input paths to process : 2
12/12/06 23:11:38 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
12/12/06 23:11:38 WARN snappy.LoadSnappy: Snappy native library not loaded
12/12/06 23:11:38 INFO mapred.JobClient: Running job: job_201212062231_0001
12/12/06 23:11:39 INFO mapred.JobClient:  map 0% reduce 0%
12/12/06 23:11:50 INFO mapred.JobClient:  map 100% reduce 0%
12/12/06 23:11:58 INFO mapred.JobClient:  map 100% reduce 33%
12/12/06 23:12:00 INFO mapred.JobClient:  map 100% reduce 100%
12/12/06 23:12:02 INFO mapred.JobClient: Job complete: job_201212062231_0001
12/12/06 23:12:02 INFO mapred.JobClient: Counters: 26
12/12/06 23:12:02 INFO mapred.JobClient:   Job Counters 
12/12/06 23:12:02 INFO mapred.JobClient:     Launched reduce tasks=1
12/12/06 23:12:02 INFO mapred.JobClient:     SLOTS_MILLIS_MAPS=14810
12/12/06 23:12:02 INFO mapred.JobClient:     Total time spent by all reduces waiting after reserving slots (ms)=0
12/12/06 23:12:02 INFO mapred.JobClient:     Total time spent by all maps waiting after reserving slots (ms)=0
12/12/06 23:12:02 INFO mapred.JobClient:     Launched map tasks=2
12/12/06 23:12:02 INFO mapred.JobClient:     Data-local map tasks=2
12/12/06 23:12:02 INFO mapred.JobClient:     SLOTS_MILLIS_REDUCES=10058
12/12/06 23:12:02 INFO mapred.JobClient:   FileSystemCounters
12/12/06 23:12:02 INFO mapred.JobClient:     FILE_BYTES_READ=11699
12/12/06 23:12:02 INFO mapred.JobClient:     HDFS_BYTES_READ=15943
12/12/06 23:12:02 INFO mapred.JobClient:     FILE_BYTES_WRITTEN=182084
12/12/06 23:12:02 INFO mapred.JobClient:     HDFS_BYTES_WRITTEN=8152
12/12/06 23:12:02 INFO mapred.JobClient:   Map-Reduce Framework
12/12/06 23:12:02 INFO mapred.JobClient:     Map input records=666
12/12/06 23:12:02 INFO mapred.JobClient:     Reduce shuffle bytes=11705
12/12/06 23:12:02 INFO mapred.JobClient:     Spilled Records=1632
12/12/06 23:12:02 INFO mapred.JobClient:     Map output bytes=23420
12/12/06 23:12:02 INFO mapred.JobClient:     CPU time spent (ms)=4300
12/12/06 23:12:02 INFO mapred.JobClient:     Total committed heap usage (bytes)=337190912
12/12/06 23:12:02 INFO mapred.JobClient:     Combine input records=2343
12/12/06 23:12:02 INFO mapred.JobClient:     SPLIT_RAW_BYTES=226
12/12/06 23:12:02 INFO mapred.JobClient:     Reduce input records=816
12/12/06 23:12:02 INFO mapred.JobClient:     Reduce input groups=762
12/12/06 23:12:02 INFO mapred.JobClient:     Combine output records=816
12/12/06 23:12:02 INFO mapred.JobClient:     Physical memory (bytes) snapshot=324112384
12/12/06 23:12:02 INFO mapred.JobClient:     Reduce output records=762
12/12/06 23:12:02 INFO mapred.JobClient:     Virtual memory (bytes) snapshot=1122086912
12/12/06 23:12:02 INFO mapred.JobClient:     Map output records=2343

命令的執行結果按上面命令的指定存儲於wc-out目錄中:

$ hadoop fs -ls wc-out
Found 3 items
-rw-r--r--   1 hadoop supergroup          0 2012-12-06 23:12 /user/hadoop/wc-out/_SUCCESS
drwxr-xr-x   - hadoop supergroup          0 2012-12-06 23:11 /user/hadoop/wc-out/_logs
-rw-r--r--   1 hadoop supergroup       8152 2012-12-06 23:11 /user/hadoop/wc-out/part-r-00000

其中的part-r-00000正是其執行結果的輸出文件,使用如下命令查看其執行結果。

$ hadoop fs -cat wc-out/part-r-00000

文件的部分內容如下所示:

"$BOOTUP"17
"$CONSOLETYPE"1
"$EUID"2
"$GRAPHICAL"1
"$HOME/.inputrc"1
"$INPUTRC"1
"$RC"3
"$STRING2
"$answer"4
"$base1
"$base"1
"$corelimit2
"$file"3
"$force"1
"$gotbase"1
"$i"1
"$killlevel"3
"$line"2
"$pid"8
"$pid_file"9
"$rc"1
"$remaining"4
"$retry"4
"$user"1
"`id2
"after"1
"color"12
"hex"1
"no1
"pidof"1

三、開發mapreduce:

儘管hadoop的框架是基於JAVA語言實現,但MapReduce程序卻未必一定要使用java來開發。

Hadoop Streaming:Hadoop提供的一個編程工具,它允許用戶使用任何可執行文件或者腳本文件作爲Mapper和Reducer;

Hadoop Pipes和SWIG:開發MapReduce程序的可兼容性 C++ API;

四、簡單配置Hadoop

4.1 設定Hadoop參數

Hadoop有很多參數,其默認配置大多數僅適用於standalone模式,雖然大多情況下在完全分佈式(Fully distributed)模式中也沒有問題,但距最優化的運行模式去相去甚遠。在生產環境中通常需要調整的參數有:

1. dfs.name.dir —— NameNode節點用於存儲HDFS元數據的本地目錄,官方建議爲/home/hadoop/dfs/name;

2. dfs.data.dir —— DataNode節點用於存儲HDFS文件數據塊的本地目錄,官方建議爲/home/hadoop/dfs/data;

3. mapred.system.dir —— HDFS中用於存儲共享的MapReduce系統文件的目錄,官方建議爲/hadoop/mapred/system;

4. mapred.local.dir —— TaskNode節點用於存儲臨時數據的本地文件目錄;

5. mapred.tasktracker.{map|reduce}.tarks.maximum —— 在TaskTracker上可同時運行的的map或reduce任務的最大數目;

6. hadoop.tmp.dir —— Hadoop臨時目錄;

7. mapred.child.java.opts —— 每個子任務可申請使用的heap大小;官方建議爲-Xmx512m;

8. mapred.reduce.tasks —— 每任務的reduce數量;

上述參數中的大多數都可以接受多個以逗號分隔的目錄,尤其是對於dfs.name.dir來說,多個目錄還可以達到冗餘的目的;而對於擁有多塊磁盤的DataNode,爲其dfs.data.dir指定多個值可以存儲數據於多個磁盤,並能通過並行加速I/O操作。爲mapred.local.dir指定多個眼光也能起到一定的加速作用。

此外,hadoop.tmp.dir對於不同的用戶來說其路徑是不相同的,事實上,應該儘量避免讓此路徑依賴用戶屬性,比如可以放在一個公共位置讓所有用戶都可以方便地訪問到。在Linux系統下,hadoop.tmp.dir的默認路徑指向了/tmp,這的確是一個公共位置,但/tmp目錄所在的文件系統大多數都有使用配額,而且空間也通常比較有限,因此,故此此路徑殊非理想之所在。建議將其指向一個有着足夠空間的文件系統上的目錄。

默認配置中,Hadoop可以在每個TaskTracker上運行四個任務(兩個map任務,兩個reduce任務),這可以通過mapred.tasktracker.{map|reduce}.tarks.maximum進行配置,通常建議其個數爲與CPU核心數目相同或者爲CPU核心數目的2倍,但其最佳值通常依賴於諸多因素,而在CPU密集型的應用場景中也不應該將其最大數目設置得過高。除了CPU之外,還應該考慮每個任務所能夠使用的的heap空間大小所帶來的影響;默認情況下,Hadoop爲每個任務指定了200MB的heap空間上限,由於每個job可能會申請使用很大的heap,因此,過高的設定可能會帶來意外的結果。

每個MapReduce任務可以通過mapred.reduce.tasks配置其運行的reduce任務數,通常也應該爲其指定一個在多數場景下都能工作良好的默認值,比如Hadoop默認將此數目指定爲1個,這對大多數任務來講都有着不錯的性能表現。而實際使用中,一般建議將此值設定爲當前Hadoop集羣可以運行的reduce任務總數的0.95倍或1.75倍。0.95這個因子意味着Hadoop集羣可以立即啓動所有的reduce任務並在map任務完成時接收數據並進行處理,而1.75則意味着先啓動部分reduce任務,執行速度快的節點上的reduce完成後可再啓動一個新的reduce任務,而速度慢的節點則無須執行此類操作。這會帶來較爲理想的負載均衡效果。

4.2 Hadoop狀態監測

Hadoop提供了fsck工具用於HDFS文件系統狀態檢測,其使用語法如下:

hadoop fsck [GENERIC_OPTIONS] <path> [-move | -delete | -openforwrite] [-files [-blocks [-locations | -racks]]]

其中GENERIC_OPTIONS是hadoop的各子命令均支持使用的選擇,如使用-conf指定配置文件等。在執行HDFS狀態檢測時,fsck會忽略正在被某客戶執行寫操作的文件,這些正在被修改或寫入數據的文件可以使用-openforwrite選項在檢測結果中予以顯示。

$ hadoop fsck / -openforwrite
FSCK started by hadoop (auth:SIMPLE) from /127.0.0.1 for path / at Thu Dec 06 23:19:35 CST 2012
.......Status: HEALTHY
 Total size:84064 B
 Total dirs:14
 Total files:7
 Total blocks (validated):6 (avg. block size 14010 B)
 Minimally replicated blocks:6 (100.0 %)
 Over-replicated blocks:0 (0.0 %)
 Under-replicated blocks:0 (0.0 %)
 Mis-replicated blocks:0 (0.0 %)
 Default replication factor:1
 Average block replication:1.0
 Corrupt blocks:0
 Missing replicas:0 (0.0 %)
 Number of data-nodes:1
 Number of racks:1
FSCK ended at Thu Dec 06 23:19:35 CST 2012 in 14 milliseconds

The filesystem under path '/' is HEALTHY

fsck會爲每個健康狀態的文件打印一個點號(.),如上面的輸出結果所示。同時,每個文件其複製塊數多於、少於配置的數目、錯誤的複製塊、損壞的數據塊及缺少數據塊的相關信息也會由fsck在執行結果中顯示。其中,多於或少於配置的數目,或錯誤的複製塊不會被視作嚴重的錯誤,而錯誤的複製塊、損壞的複製塊或缺少複製塊則意味着數據的永久性丟失。使用fsck的-delete選項則可用於在檢測過程中刪除這些損壞狀態的文件,-move選項則可用於將這些文件移動至lost+found目錄中。


fsck命令格式中的[-files [-blocks [-locations | -racks]]]用於讓其輸出更爲詳細的檢測信息,-files後的每個選項都依賴於其前面選項,因此,要使用-blocks則必須同時使用-files,要使用-locations則必須同時使用-blocks和-files;而-locations和-racks則既可爲同級別的選項,使用時二選一,也可將-racksg與-locations同時使用。-files選項用於輸出文件自身的狀態信息,如文件路徑、大小、佔用的數據塊及狀態;-blocks選項用於輸出每個數據塊的相關信息;-locations用於輸出每個複製塊的具體位置;-racks則用於顯示數據節點位置的拓撲信息。

$ hadoop fsck / -openforwrite -files -blocks -locations -racks
FSCK started by hadoop (auth:SIMPLE) from /127.0.0.1 for path / at Thu Dec 06 23:20:56 CST 2012
/ <dir>
/hadoop <dir>
/hadoop/temp <dir>
/hadoop/temp/mapred <dir>
/hadoop/temp/mapred/staging <dir>
/hadoop/temp/mapred/staging/hadoop <dir>
/hadoop/temp/mapred/staging/hadoop/.staging <dir>
/hadoop/temp/mapred/system <dir>
/hadoop/temp/mapred/system/jobtracker.info 4 bytes, 1 block(s):  OK
0. blk_8000193754097372869_1002 len=4 repl=1 [/default-rack/127.0.0.1:50010]
/user <dir>
/user/hadoop <dir>
/user/hadoop/wc-in <dir>
/user/hadoop/wc-in/functions 14291 bytes, 1 block(s):  OK
0. blk_-2535948061878952264_1003 len=14291 repl=1 [/default-rack/127.0.0.1:50010]
/user/hadoop/wc-in/profile 1426 bytes, 1 block(s):  OK
0. blk_5095873178802140996_1004 len=1426 repl=1 [/default-rack/127.0.0.1:50010]
/user/hadoop/wc-out <dir>
/user/hadoop/wc-out/_SUCCESS 0 bytes, 0 block(s):  OK
/user/hadoop/wc-out/_logs <dir>
/user/hadoop/wc-out/_logs/history <dir>
/user/hadoop/wc-out/_logs/history/job_201212062231_0001_1354806698562_hadoop_word+count 14687 bytes, 1 block(s):  OK
0. blk_-6941616318716878099_1014 len=14687 repl=1 [/default-rack/127.0.0.1:50010]
/user/hadoop/wc-out/_logs/history/localhost_1354804300040_job_201212062231_0001_conf.xml 45504 bytes, 1 block(s):  OK
0. blk_438023500023782106_1011 len=45504 repl=1 [/default-rack/127.0.0.1:50010]
/user/hadoop/wc-out/part-r-00000 8152 bytes, 1 block(s):  OK
0. blk_-4078455009405364683_1013 len=8152 repl=1 [/default-rack/127.0.0.1:50010]
Status: HEALTHY
 Total size:84064 B
 Total dirs:14
 Total files:7
 Total blocks (validated):6 (avg. block size 14010 B)
 Minimally replicated blocks:6 (100.0 %)
 Over-replicated blocks:0 (0.0 %)
 Under-replicated blocks:0 (0.0 %)
 Mis-replicated blocks:0 (0.0 %)
 Default replication factor:1
 Average block replication:1.0
 Corrupt blocks:0
 Missing replicas:0 (0.0 %)
 Number of data-nodes:1
 Number of racks:1
FSCK ended at Thu Dec 06 23:20:56 CST 2012 in 28 milliseconds

The filesystem under path '/' is HEALTHY

此外,也可以使用hadoop的dfsadmin打印hdfs文件系統的狀態信息。

$ hadoop dfsadmin -report
Configured Capacity: 41604677632 (38.75 GB)
Present Capacity: 38942863360 (36.27 GB)
DFS Remaining: 38942621696 (36.27 GB)
DFS Used: 241664 (236 KB)
DFS Used%: 0%
Under replicated blocks: 0
Blocks with corrupt replicas: 0
Missing blocks: 0
-------------------------------------------------
Datanodes available: 1 (1 total, 0 dead)
Name: 127.0.0.1:50010
Decommission Status : Normal
Configured Capacity: 41604677632 (38.75 GB)
DFS Used: 241664 (236 KB)
Non DFS Used: 2661814272 (2.48 GB)
DFS Remaining: 38942621696(36.27 GB)
DFS Used%: 0%
DFS Remaining%: 93.6%
Last contact: Thu Dec 06 23:22:28 CST 2012

4.3 啓用HDFS的回收站

HDFS支持文件刪除的“回收站”功能,被刪除的文件不會立即從存儲空間中擦除,而是先被移入用戶家目錄中的.Trash子目錄中,當文件刪除的時長超出事先預定義的時長後就會被自動從回收站中刪除,在此之前,用戶可以隨時恢復被刪除的文件。默認情況下,HDFS禁用了回收站功能,如果想啓用,只需要在core-site.xml配置文件中使用fs.trash.interval定義刪除文件的保留時長即可,其時長的默認單位爲分鐘,值0表示禁用回收站。如下所示的例子中,定義了被刪除文件的保留時長爲7天。

<property>
<name>fs.trash.interval</name>
<value>10080</value>
</property>

五、完全分佈式Hadoop

在需要時,可以通過conf/hadoop-env.sh腳本自定義Hadoop進程的環境變量,至少,JAVA_HOME是每個節點所必須事先正確定義的環境變量。另外,也可以通過HADOOP_*_OPTS爲對應的Hadoop的5類進程(NameNode、DataNode、SecondaryNameNode、JobTracker和TaskTracker)定義運行參數,比如:HADOOP_NAMENODE_OPTS用於定義NameNode進程的運行參數,以此類推。

此外,HADOOP_LOG_DIR用於定義進程日誌文件的存儲目錄,HADOOP_HEAPSIZE用於定義Hadoop進程可用的堆空間大小,單位是MB,默認爲1000MB。

5.1、配置Hadoop進程

5.1.1 配置NomeNode的URI

在配置文件conf/core-site.xml中定義fs.default.name參數即可。

5.1.2 配置HDFS的相關參數

在配置文件conf/hdfs-site.xml中定義dfs.name.dir(NameNode用於存儲名稱空間和事務日誌的本地文件系統路徑)和dfs.data.dir(DataNode用於存儲數據塊的一個或多個本地文件系統路徑,有多個路徑時彼此間用逗號隔開)兩個參數即可。

5.1.3 配置Jobtracker和TaskTracker進程的相關參數

在conf/mapred-site.xml文件中進行,主要有以下參數:

mapred.job.tracker:JobTracker進程所在主機的主機名(或IP)和端口;

mapred.system.dir:MapReduce用於存儲系統文件的HDFS文件系統路徑,如/hadoop/mapred/system/;

mapred.local.dir:MapReduce用於存儲臨時數據的本地文件系統路徑,指定多個路徑可以分散I/O壓力,彼此間需要使用逗號分隔;

mapred.tasktracker.{map|reduce}.tasks.maximum:在每一個TaskTracker上可以運行的MapReduce任務的最大數量,默認爲2(maps任務和reduces任務各兩個);

dfs.hosts/dfs.hosts.exclude:允許使用或禁止使用的DataNode列表;

mapred.hosts/mapred.hosts.exclude:允許使用或禁用的TaskTracker列表;

mapred.queue.names:可以接受提交的任務的隊列名稱列表;MapReduce至少支持一個默認的“default”隊列,因此,此參數的值列表中中必須要包含default;

mapred.queue.queue-name.acl-administer-jobs:可以查看作業詳情的用戶和組的列表;名稱和組各自使用一個列表,兩個列表之間使用空格分隔,而每個列表內的名稱則使用逗號分隔,如:user1,user2 grp1,grp2;如果僅定義組列表而不提供用戶列表,在組列表之前加一個空白字符即可;

5.2、生產環境中常用的配置

僅參考:http://www.cnblogs.com/zhj983452257/p/5399414.html

......

......

......


5.3、安裝完全分佈式Hadoop

5.3.1 安裝準備工作

本安裝示例將使用三臺主機(RHEL 5.8 32bit)來實現,其規劃如下所示:

IP地址主機名運行的進程或扮演的角色

172.16.100.11 master.shine.comNameNode,JobTracker

172.16.100.12datanode.shine.comDataNode,TaskTracker

172.16.100.13snn.shine.comSecondaryNameNode

用到的應用程序:

JDK: jdk-7u5-linux-i586.rpm

Hadoop:hadoop-0.20.2-cdh3u5.tar.gz

先在集羣中的每個節點上建立運行hadoop進程的用戶hadoop並給其設定密碼。

# useradd hadoop
# echo "password" | passwd --stdin hadoop

設置集羣各節點的/etc/hosts文件內容如下:

172.16.100.11master.shine.commaster
172.16.100.12datanode.shine.comdatanode
172.16.100.13snn.shine.comsnn

而後配置master節點的hadoop用戶能夠以基於密鑰的驗正方式登錄其它各節點,以便啓動進程並執行監控等額外的管理工作。以下命令在master節點上執行即可。

[root@master ~]# su - hadoop
[hadoop@master ~]$ ssh-keygen -t rsa -P '' 
[hadoop@master ~]$ ssh-copy-id -i .ssh/id_rsa.pub hadoop@datanode
[hadoop@master ~]$ ssh-copy-id -i .ssh/id_rsa.pub hadoop@snn

5.3.2 安裝JDK

以下操作需要在每個節點上執行一遍。

編輯/etc/profile.d/java.sh,在文件中添加如下內容:

JAVA_HOME=/usr/java/latest/
PATH=$JAVA_HOME/bin:$PATH
export JAVA_HOME PATH

切換至hadoop用戶,並執行如下命令測試jdk環境配置是否就緒。

# su - hadoop
$ java -version
java version "1.7.0_05"
Java(TM) SE Runtime Environment (build 1.7.0_05-b05)
Java HotSpot(TM) Client VM (build 23.1-b03, mixed mode, sharing)

5.3.3 安裝Hadoop

集羣中的每個節點均需要安裝Hadoop,以根據配置或需要啓動相應的進程等,因此,以下安裝過程需要在每個節點上分別執行。

# tar xf hadoop-0.20.2-cdh3u5.tar.gz -C /usr/local
# chown -R hadoop:hadoop /usr/local/hadoop-0.20.2-cdh3u5
# ln -sv /usr/local/hadoop-0.20.2-cdh3u5 /usr/local/hadoop

然後編輯/etc/profile,設定HADOOP_HOME環境變量的值爲hadoop的解壓目錄,並讓其永久有效。編輯/etc/profile.d/hadoop.sh,添加如下內容:

HADOOP_HOME=/usr/local/hadoop
PATH=$HADOOP_HOME/bin:$PATH
export HADOOP_BASE PATH

切換至hadoop用戶,並執行如下命令測試jdk環境配置是否就緒。

$ hadoop version
Hadoop 0.20.2-cdh3u5
Subversion git://ubuntu-slave02/var/lib/jenkins/workspace/CDH3u5-Full-RC/build/cdh3/hadoop20/0.20.2-cdh3u5/source -r 30233064aaf5f2492bc687d61d72956876102109
Compiled by jenkins on Fri Oct  5 17:21:34 PDT 2012
From source with checksum de1770d69aa93107a133657faa8ef467

5.3.4 配置Hadoop

集羣中的每個節點上Hadoop的配置均相同,Hadoop在啓動時會根據配置文件判定當前節點的角色及所需要運行的進程等,因此,下述的配置文件修改需要在每一個節點上運行。

(1) 修改/usr/local/hadoop/conf/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://master.shine.com:8020</value>
        <final>true</final>
        <description>The name of the default file system. A URI whose scheme and authority determine the FileSystem implimentation.</description>
    </property>
</configuration>

(2)修改/usr/local/hadoop/conf/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>master.shine.com:8021</value>
        <final>true</final>
        <description>The host and port that the MapReduce JobTracker runs at. </description>
    </property>
</configuration>

(3) 修改/usr/local/hadoop/conf/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>
<description>The actual number of replications can be specified when the file is created.</description>
    </property>
<property>
        <name>dfs.data.dir</name>
        <value>/hadoop/data</value>
        <final>ture</final>
        <description>The directories where the datanode stores blocks.</description>
    </property>
<property>
        <name>dfs.name.dir</name>
        <value>/hadoop/name</value>
        <final>ture</final>
        <description>The directories where the namenode stores its persistent matadata.</description>
    </property>
<property>
        <name>fs.checkpoint.dir</name>
        <value>/hadoop/namesecondary</value>
        <final>ture</final>
        <description>The directories where the secondarynamenode stores checkpoints.</description>
    </property>
</configuration>

說明:根據此配置,需要事先在各節點上創建/hadoop/,並讓hadoop用戶對其具有全部權限。也可以不指定最後三個屬性,讓Hadoop爲其使用默認位置。

(4)修改/usr/local/hadoop/conf/masters文件,指定SecondaryNameNode節點的主機名或IP地址,本示例中爲如下內容:

snn.shine.com

(5)修改/usr/local/hadoop/conf/slaves文件,指定各DataNode節點的主機名或IP地址,本示例中只有一個DataNode:

datanode.shine.com

(6)初始化數據節點,在master上執行如下命令

$ hadoop namenode -format

5.3.5 啓動Hadoop

在master節點上執行Hadoop的start-all.sh腳本即可實現啓動整個集羣。

[hadoop@master ~]$ start-all.sh

其輸出內容如下所示:

starting namenode, logging to /usr/local/hadoop/logs/hadoop-hadoop-namenode-master.shine.com.out
datanode.shine.com: starting datanode, logging to /usr/local/hadoop/logs/hadoop-hadoop-datanode-datanode.shine.com.out
snn.shine.com: starting secondarynamenode, logging to /usr/local/hadoop/logs/hadoop-hadoop-secondarynamenode-node3.shine.com.out
starting jobtracker, logging to /usr/local/hadoop/logs/hadoop-hadoop-jobtracker-master.shine.com.out
datanode.shine.com: starting tasktracker, logging to /usr/local/hadoop/logs/hadoop-hadoop-tasktracker-datanode.shine.com.out

如果要停止Hadoop的各進程,則使用stop-all.sh腳本即可。

不過,在一個較大規模的集羣環境中,NameNode節點需要在內在中維護整個名稱空間中的文件和塊的元數據信息,因此,其有着較大的內在需求;而在運行着衆多MapReduce任務的環境中,JobTracker節點會用到大量的內存和CPU資源,因此,此場景中通常需要將NameNode和JobTracker運行在不同的物理主機上,這也意味着HDFS集羣的主從節點與MapReduce的主從節點將分屬於不同的拓撲。啓動HDFS的主從進程則需要在NameNode節點上使用start-dfs.sh腳本,而啓動MapReduce的各進程則需要在JobTracker節點上通過start-mapred.sh腳本進行。這兩個腳本事實上都是通過hadoop-daemons.sh腳本來完成進程啓動的。

5.4 環境設定

5.4.1 內存設定

默認情況下,Hadoop爲每個進程分配1000MB(1GB)的內存空間,但這可以在hadoop-env.sh文件中通過HADOOP_HEAPSIZE環境變量進行調整。此外,TaskTracker會爲worker主機上的每個map或reduce任務的分別啓動一個JVM,這些JVM都需要在進程的HEAP中申請用到內存空間。每個TaskTracker可同時運行的map任務總數和reduce任務總數分別由mapred.tasktracker.map.tasks.maximum和mapred.tasktracker.reduce.tasks.maximum這兩個屬性進行指定,而它們的默認值都爲2。用於運行map或reduce任務的JVM可用內存大小可由mapred.child.java.opts屬性指定,其默認設定爲-Xmx200m,意指每個任務可以使用最多200MB的內存空間。由此算來,每個worker主機默認將使用2800MB的內存空間。

除了使用mapred.child.java.opts爲每個JVM爲map任務和reduce任務設定相同可用內存屬性之外,還可以使用mapreduce.map.java.opts和mapreduce.reduce.java.opts分別設定map任務和reduce任務的JVM可用內存的屬性。

在TaskTracker上可同時運行的任務數取決於其主機的CPU數量。由於MapReduce作業大多爲I/O密集型應用,因此,讓同行運行任務數多於CPU的個數可以提高資源利用效率,其可以多出的數量取決於實際的作業本身。這裏有一個通用法則,即讓同行運行的作業數量爲CPU數量的1至2之間的數字倍數,比如作業數1.5倍於CPU數。與此同時,一定要注意系統上可用內存的數量是否符合任務數的設定,比如在一個4顆CPU的DataNode上,可以設定mapred.tasktracker.map.tasks.maximum和mapred.tasktrackers.reduce.tasks.maximum屬性的值都爲3(不是4個,因爲datanode和tasktracker都是運行的任務,它們要佔去兩個名額),假設每個任務的可用內存爲400MB,那麼這些作業總共需要的內存數爲6*400MB,即2.4GB,考慮到操作系統及其它進程所需用的內存等,這個數值可能需要更大。

在hadoop-env.sh文件中,可以使用HADOOP_NAMENODE_OPTS、HADOOP_SECONDARYNAMENODE_OPTS、HADOOP_DATANODE_OPTS、HADOOP_BALANCER_OPTS、HADOOP_JOBTRACKER_OPTS變量分別爲對應的5類進程設定運行參數,比如可以使用HADOOP_NAMENODE_OPTS單獨設定namenode進程使用不的HEAPSIZE大小。

5.4.2 Hadoop日誌

Hadoop的系統日誌默認存放於其安裝目錄中的logs子目錄,如果需要自定義其存儲位置,可以在hadoop-env.sh中設定HADOOP_LOG_DIR環境變量來指定新位置。Hadoop的每個進程均會生成兩個日誌文件,一個是由log4j生成的並以.log爲後綴的日誌文件,另一個是以.out爲後綴的日誌文件,它負責記錄發往標準輸出和錯誤輸出的信息。

大多數應用的日誌住處均發送至.log類的文件中,因此在故障排查時其也是最需要關注的日誌文件。然後,Hadoop爲log4j提供的默認配置中,其每天會自動做一次日誌滾動,並且永遠不會刪除日誌文件,因此,管理員需要手動歸檔並刪除老舊的日誌文件。.out類的日誌文件中很少出現信息,而且,Hadoop的每次重啓都會導致日誌自動滾動,並只會保存最至5次的滾動日誌文件版本。

除了後綴不同之外,這兩種日誌文件的名稱格式是一樣的,默認均爲hadoop-<username>-<processname>-<hostname>,比如hadoop-hadoop-namenode-master.shine.com.log。可以在hadoop-env.sh文件中使用HADOOP_IDENT_STRING變量將日誌文件名稱格式中的<username>限制爲所需要的字符串。

5.4.3 SSH相關的設定

Hadoop運行時,它利用控制腳本(如start-dfs.sh)在master節點上基於SSH遠程管理各worker節點上的進程,因此,爲SSH設定合適的參數將用助於Hadoop的健壯性,如合適的連接超時時間(ConnectTimeout)將有助於Hadoop避免被失效的節點阻塞,將StrictHostKeyChecking設定爲no將能夠使得master自動添加各節點的主機密鑰等。

Hadoop的控制腳本可以使用rsync將配置文件同步至集羣中的其它節點,默認爲禁用。如果需要,可以通過HADOOP_MASTER變量將其啓用。不過,由於各點上HADOOP_MASTER默認均爲禁用,因此,其第一次配置還是需要其它的方式進行。

其它各SSH相關參數說明及其用法在hadoop-env.sh中均有詳細註釋,因此,這裏不再給出進一步信息。

5.5 Hadoop的其它常用屬性

5.5.1 緩衝大小(Buffer size)

Hadoop爲其I/O操作使用了4KB的緩衝區容量,這個值是相當保守的。在當今的硬件和操作系統上,可以安全地增大此值以提高系統性能;一般說來,128KB(131072 bytes)是比較理想的設定。如果需要,可以在core-site.xml中通過io.file.buffer.size屬性進行定義。

5.5.2 HDFS塊大小

HDFS默認塊大小爲64MB,然而128MB(134,217,728 bytes)是更常用的設定,甚至有些集羣中使用了256MB。較大的塊可以有效降低NameNode上的內存壓力,並能支持使用更多的數據量。如果需要,可以在hdfs-site.xml文件中使用dfs.block.size屬性進行定義。

5.5.3 慢啓動Reduce任務

在一個作業中,默認情況下調度器會在map任務完成5%時開始調度啓動當前作業的reduce任務。對於較大的作業來說,過早地啓動reduce會導致集羣性能的下降。在mapred-site.xml文件中爲mapred.reduce.slowstart.completed.maps屬性來設定一個更大的值(比如0.8,即80%)可以在更晚的時間點啓動reduce作業。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章