歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux基礎 >> 關於Linux

分布式計算開源框架Hadoop入門實踐

在SIP項目設計的過程中,對於它龐大的日志在開始時就考慮使用任務分解的多線程處理模式來分析統計,在我從前寫的文章《Tiger Concurrent Practice --日志分析並行分解設計與實現》中有所提到。但是由於統計的內容暫時還是十分簡單,所以就采用Memcache作為計數器,結合MySQL就完成了訪問控制以及統計的工作。然而未來,對於海量日志分析的工作,還是需要有所准備。現在最火的技術詞匯莫過於“雲計算”,在Open API日益盛行的今天,互聯網應用的數據將會越來越有價值,如何去分析這些數據,挖掘其內在價值,就需要分布式計算來支撐海量數據的分析工作。

  回過頭來看,早先那種多線程,多任務分解的日志分析設計,其實是分布式計算的一個單機版縮略,如何將這種單機的工作進行分拆,變成協同工作的集群,其實就是分布式計算框架設計所涉及的。在去年參加BEA大會的時候,BEA和VMWare合作采用虛擬機來構建集群,無非就是希望使得計算機硬件能夠類似於應用程序中資源池的資源,使用者無需關心資源的分配情況,從而最大化了硬件資源的使用價值。分布式計算也是如此,具體的計算任務交由哪一台機器執行,執行後由誰來匯總,這都由分布式框架的Master來抉擇,而使用者只需簡單地將待分析內容提供給分布式計算系統作為輸入,就可以得到分布式計算後的結果。

  Hadoop是Apache開源組織的一個分布式計算開源框架,在很多大型網站上都已經得到了應用,如亞馬遜、Facebook和Yahoo等等。對於我來說,最近的一個使用點就是服務集成平台的日志分析。服務集成平台的日志量將會很大,而這也正好符合了分布式計算的適用場景(日志分析和索引建立就是兩大應用場景)。

  當前沒有正式確定使用,所以也是自己業余摸索,後續所寫的相關內容,都是一個新手的學習過程,難免會有一些錯誤,只是希望記錄下來可以分享給更多志同道合的朋友。

 什麼是Hadoop?

  搞什麼東西之前,第一步是要知道What(是什麼),然後是Why(為什麼),最後才是How(怎麼做)。但很多開發的朋友在做了多年項目以後,都習慣是先How,然後What,最後才是Why,這樣只會讓自己變得浮躁,同時往往會將技術誤用於不適合的場景。

  Hadoop框架中最核心的設計就是:MapReduce和HDFS。MapReduce的思想是由Google的一篇論文所提及而被廣為流傳的,簡單的一句話解釋MapReduce就是“任務的分解與結果的匯總”。HDFS是Hadoop分布式文件系統(Hadoop Distributed File System)的縮寫,為分布式計算存儲提供了底層支持。

  MapReduce從它名字上來看就大致可以看出個緣由,兩個動詞Map和Reduce,“Map(展開)”就是將一個任務分解成為多個任務,“Reduce”就是將分解後多任務處理的結果匯總起來,得出最後的分析結果。這不是什麼新思想,其實在前面提到的多線程,多任務的設計就可以找到這種思想的影子。不論是現實社會,還是在程序設計中,一項工作往往可以被拆分成為多個任務,任務之間的關系可以分為兩種:一種是不相關的任務,可以並行執行;另一種是任務之間有相互的依賴,先後順序不能夠顛倒,這類任務是無法並行處理的。回到大學時期,教授上課時讓大家去分析關鍵路徑,無非就是找最省時的任務分解執行方式。在分布式系統中,機器集群就可以看作硬件資源池,將並行的任務拆分,然後交由每一個空閒機器資源去處理,能夠極大地提高計算效率,同時這種資源無關性,對於計算集群的擴展無疑提供了最好的設計保證。(其實我一直認為Hadoop的卡通圖標不應該是一個小象,應該是螞蟻,分布式計算就好比螞蟻吃大象,廉價的機器群可以匹敵任何高性能的計算機,縱向擴展的曲線始終敵不過橫向擴展的斜線)。任務分解處理以後,那就需要將處理以後的結果再匯總起來,這就是Reduce要做的工作。

圖1:MapReduce結構示意圖

  上圖就是MapReduce大致的結構圖,在Map前還可能會對輸入的數據有Split(分割)的過程,保證任務並行效率,在Map之後還會有Shuffle(混合)的過程,對於提高Reduce的效率以及減小數據傳輸的壓力有很大的幫助。後面會具體提及這些部分的細節。

  HDFS是分布式計算的存儲基石,Hadoop的分布式文件系統和其他分布式文件系統有很多類似的特質。分布式文件系統基本的幾個特點:

  對於整個集群有單一的命名空間。

  數據一致性。適合一次寫入多次讀取的模型,客戶端在文件沒有被成功創建之前無法看到文件存在。

  文件會被分割成多個文件塊,每個文件塊被分配存儲到數據節點上,而且根據配置會由復制文件塊來保證數據的安全性。

圖2:HDFS結構示意圖

  上圖中展現了整個HDFS三個重要角色:NameNode、DataNode和Client。NameNode可以看作是分布式文件系統中的管理者,主要負責管理文件系統的命名空間、集群配置信息和存儲塊的復制等。NameNode會將文件系統的Meta-data存儲在內存中,這些信息主要包括了文件信息、每一個文件對應的文件塊的信息和每一個文件塊在DataNode的信息等。DataNode是文件存儲的基本單元,它將Block存儲在本地文件系統中,保存了Block的Meta-data,同時周期性地將所有存在的Block信息發送給NameNode。Client就是需要獲取分布式文件系統文件的應用程序。這裡通過三個操作來說明他們之間的交互關系。

文件寫入:

  Client向NameNode發起文件寫入的請求。

  NameNode根據文件大小和文件塊配置情況,返回給Client它所管理部分DataNode的信息。

  Client將文件劃分為多個Block,根據DataNode的地址信息,按順序寫入到每一個DataNode塊中。

  文件讀取:

  Client向NameNode發起文件讀取的請求。

  NameNode返回文件存儲的DataNode的信息。

  Client讀取文件信息。

  文件Block復制:

  NameNode發現部分文件的Block不符合最小復制數或者部分DataNode失效。

  通知DataNode相互復制Block。

  DataNode開始直接相互復制。

  最後再說一下HDFS的幾個設計特點(對於框架設計值得借鑒):

  Block的放置:默認不配置。一個Block會有三份備份,一份放在NameNode指定的DataNode,另一份放在與指定DataNode非同一Rack上的DataNode,最後一份放在與指定DataNode同一Rack上的DataNode上。備份無非就是為了數據安全,考慮同一Rack的失敗情況以及不同Rack之間數據拷貝性能問題就采用這種配置方式。

  心跳檢測DataNode的健康狀況,如果發現問題就采取數據備份的方式來保證數據的安全性。

  數據復制(場景為DataNode失敗、需要平衡DataNode的存儲利用率和需要平衡DataNode數據交互壓力等情況):這裡先說一下,使用HDFS的balancer命令,可以配置一個Threshold來平衡每一個DataNode磁盤利用率。例如設置了Threshold為10%,那麼執行balancer命令的時候,首先統計所有DataNode的磁盤利用率的均值,然後判斷如果某一個DataNode的磁盤利用率超過這個均值Threshold以上,那麼將會把這個DataNode的block轉移到磁盤利用率低的DataNode,這對於新節點的加入來說十分有用。

  數據交驗:采用CRC32作數據交驗。在文件Block寫入的時候除了寫入數據還會寫入交驗信息,在讀取的時候需要交驗後再讀入。

  NameNode是單點:如果失敗的話,任務處理信息將會紀錄在本地文件系統和遠端的文件系統中。

  數據管道性的寫入:當客戶端要寫入文件到DataNode上,首先客戶端讀取一個Block然後寫到第一個DataNode上,然後由第一個DataNode傳遞到備份的DataNode上,一直到所有需要寫入這個Block的NataNode都成功寫入,客戶端才會繼續開始寫下一個Block。

  安全模式:在分布式文件系統啟動的時候,開始的時候會有安全模式,當分布式文件系統處於安全模式的情況下,文件系統中的內容不允許修改也不允許刪除,直到安全模式結束。安全模式主要是為了系統啟動的時候檢查各個DataNode上數據塊的有效性,同時根據策略必要的復制或者刪除部分數據塊。運行期通過命令也可以進入安全模式。在實踐過程中,系統啟動的時候去修改和刪除文件也會有安全模式不允許修改的出錯提示,只需要等待一會兒即可。

  下面綜合MapReduce和HDFS來看Hadoop的結構:

圖3:Hadoop結構示意圖

  在Hadoop的系統中,會有一台Master,主要負責NameNode的工作以及JobTracker的工作。JobTracker的主要職責就是啟動、跟蹤和調度各個Slave的任務執行。還會有多台Slave,每一台Slave通常具有DataNode的功能並負責TaskTracker的工作。TaskTracker根據應用要求來結合本地數據執行Map任務以及Reduce任務。

  說到這裡,就要提到分布式計算最重要的一個設計點:Moving Computation is Cheaper than Moving Data。就是在分布式處理中,移動數據的代價總是高於轉移計算的代價。簡單來說就是分而治之的工作,需要將數據也分而存儲,本地任務處理本地數據然後歸總,這樣才會保證分布式計算的高效性。

 

  為什麼要選擇Hadoop?

  說完了What,簡單地說一下Why。官方網站已經給了很多的說明,這裡就大致說一下其優點及使用的場景(沒有不好的工具,只用不適用的工具,因此選擇好場景才能夠真正發揮分布式計算的作用):

  可擴展:不論是存儲的可擴展還是計算的可擴展都是Hadoop的設計根本。

  經濟:框架可以運行在任何普通的PC上。

  可靠:分布式文件系統的備份恢復機制以及MapReduce的任務監控保證了分布式處理的可靠性。

  高效:分布式文件系統的高效數據交互實現以及MapReduce結合Local Data處理的模式,為高效處理海量的信息作了基礎准備。

  使用場景:個人覺得最適合的就是海量數據的分析,其實Google最早提出MapReduce也就是為了海量數據分析。同時HDFS最早是為了搜索引擎實現而開發的,後來才被用於分布式計算框架中。海量數據被分割於多個節點,然後由每一個節點並行計算,將得出的結果歸並到輸出。同時第一階段的輸出又可以作為下一階段計算的輸入,因此可以想象到一個樹狀結構的分布式計算圖,在不同階段都有不同產出,同時並行和串行結合的計算也可以很好地在分布式集群的資源下得以高效的處理。

其實參看Hadoop官方文檔已經能夠很容易配置分布式框架運行環境了,不過這裡既然寫了就再多寫一點,同時有一些細節需要注意的也說明一下,其實也就是這些細節會讓人摸索半天。Hadoop可以單機跑,也可以配置集群跑,單機跑就不需要多說了,只需要按照Demo的運行說明直接執行命令即可。這裡主要重點說一下集群配置運行的過程。

  環境

  7台普通的機器,操作系統都是Linux。內存和CPU就不說了,反正Hadoop一大特點就是機器在多不在精。JDK必須是1.5以上的,這個切記。7台機器的機器名務必不同,後續會談到機器名對於MapReduce有很大的影響。

  部署考慮

  正如上面我描述的,對於Hadoop的集群來說,可以分成兩大類角色:Master和Slave,前者主要配置NameNode和JobTracker的角色,負責總管分布式數據和分解任務的執行,後者配置DataNode和TaskTracker的角色,負責分布式數據存儲以及任務的執行。本來我打算看看一台機器是否可以配置成Master,同時也作為Slave使用,不過發現在NameNode初始化的過程中以及TaskTracker執行過程中機器名配置好像有沖突(NameNode和TaskTracker對於Hosts的配置有些沖突,究竟是把機器名對應IP放在配置前面還是把Localhost對應IP放在前面有點問題,不過可能也是我自己的問題吧,這個大家可以根據實施情況給我反饋)。最後反正決定一台Master,六台Slave,後續復雜的應用開發和測試結果的比對會增加機器配置。

  實施步驟

  在所有的機器上都建立相同的目錄,也可以就建立相同的用戶,以該用戶的home路徑來做hadoop的安裝路徑。例如我在所有的機器上都建立了/home/wenchu。

  下載Hadoop,先解壓到Master上。這裡我是下載的0.17.1的版本。此時Hadoop的安裝路徑就是/home/wenchu/hadoop-0.17.1。

 解壓後進入conf目錄,主要需要修改以下文件:hadoop-env.sh,hadoop-site.xml、masters、slaves。

  Hadoop的基礎配置文件是hadoop-default.xml,看Hadoop的代碼可以知道,默認建立一個Job的時候會建立Job的Config,Config首先讀入hadoop-default.xml的配置,然後再讀入hadoop-site.xml的配置(這個文件初始的時候配置為空),hadoop-site.xml中主要配置你需要覆蓋的hadoop-default.xml的系統級配置,以及你需要在你的MapReduce過程中使用的自定義配置(具體的一些使用例如final等參考文檔)。

  以下是一個簡單的hadoop-site.xml的配置:

DE><?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>//你的namenode的配置,機器名加端口
  <value>hdfs://10.2.224.46:54310/</value>
< /property>
< property>
  <name>mapred.job.tracker</name>//你的JobTracker的配置,機器名加端口
  <value>hdfs://10.2.224.46:54311/</value>
< /property>
< property>
  <name>dfs.replication</name>//數據需要備份的數量,默認是三
  <value>1</value>
< /property>
< property>
  <name>hadoop.tmp.dir</name>//Hadoop的默認臨時路徑,這個最好配置,如果在新增節點或者其他情況下莫名其妙的DataNode啟動不了,就刪除此文件中的tmp目錄即可。不過如果刪除了NameNode機器的此目錄,那麼就需要重新執行NameNode格式化的命令。
  <value>/home/wenchu/hadoop/tmp/</value>
< /property>
< property>
  <name>mapred.child.java.opts</name>//java虛擬機的一些參數可以參照配置
  <value>-Xmx512m</value>
< /property>
< property>
 <name>dfs.block.size</name>//block的大小,單位字節,後面會提到用處,必須是512的倍數,因為采用crc作文件完整性校驗,默認配置512是checksum的最小單元。
 <value>5120000</value>
 <description>The default block size for new files.</description>
< /property>
< /configuration>DE>

  hadoop-env.sh文件只需要修改一個參數:

DE># The java implementation to use. Required.
export JAVA_HOME=/usr/ali/jdk1.5.0_10DE>

  配置你的Java路徑,記住一定要1.5版本以上,免得莫名其妙出現問題。

  Masters中配置Masters的IP或者機器名,如果是機器名那麼需要在/etc/hosts中有所設置。Slaves中配置的是Slaves的IP或者機器名,同樣如果是機器名需要在/etc/hosts中有所設置。范例如下,我這裡配置的都是IP:

DE>Masters:
10.2.224.46
 Slaves:
10.2.226.40
10.2.226.39
10.2.226.38
10.2.226.37
10.2.226.41
10.2.224.36DE>

  建立Master到每一台Slave的SSH受信證書。由於Master將會通過SSH啟動所有Slave的Hadoop,所以需要建立單向或者雙向證書保證命令執行時不需要再輸入密碼。在Master和所有的Slave機器上執行:ssh-keygen -t rsa。執行此命令的時候,看到提示只需要回車。然後就會在/root/.ssh/下面產生id_rsa.pub的證書文件,通過scp將Master機器上的這個文件拷貝到Slave上(記得修改名稱),例如:scp root@masterIP:/root/.ssh/id_rsa.pub /root/.ssh/46_rsa.pub,然後執行cat /root/.ssh/46_rsa.pub >>/root/.ssh/authorized_keys,建立authorized_keys文件即可,可以打開這個文件看看,也就是rsa的公鑰作為key,user@IP作為value。此時可以試驗一下,從master ssh到slave已經不需要密碼了。由slave反向建立也是同樣。為什麼要反向呢?其實如果一直都是Master啟動和關閉的話那麼沒有必要建立反向,只是如果想在Slave也可以關閉Hadoop就需要建立反向。

  將Master上的Hadoop通過scp拷貝到每一個Slave相同的目錄下,根據每一個Slave的Java_HOME的不同修改其hadoop-env.sh。

 修改Master上/etc/profile:

Copyright © Linux教程網 All Rights Reserved