看懂Hadoop集羣原理與實現方式

 這篇文章將會逐步介紹 Hadoop 集羣的實現原理以及Hadoop集羣的拓撲結構。並讓大家通過拓撲圖的形式直觀的瞭解 Hadoop 集羣是如何搭建、運行以及各個節點之間如何相互調用、每個節點是如何工作以及各個節點的作用是什麼。明白這一點將會對學習 Hadoop 有很大的幫助。首先,我們開始瞭解 Hadoop 的基礎知識,以及 Hadoop 集羣的工作原理。
看懂Hadoop集羣原理與實現方式
       在Hadoop部署中,有三種服務器角色,他們分別是客戶端、Masters節點以及Slave 節點。Master 節點,Masters 節點又稱主節點,主節點負責監控兩個核心功能:大數據存儲(HDFS)以及數據並行計算(Map Reduce)。其中,Name Node 負責監控以及協調數據存儲(HDFS)的工作,Job Tracker 則負責監督以及協調 Map Reduce 的並行計算。 而Slave 節點則負責具體的工作以及數據存儲。每個 Slave 運行一個 Data Node 和一個 Task Tracker 守護進程。這兩個守護進程負責與 Master 節點通信。Task Tracker 守護進程與 Job Tracker 相互作用,而 Data Node 守護進程則與 Name Node 相互作用。

       所有的集羣配置都會存在於客戶端服務器,但是客戶端服務器不屬於 Master 以及 Salve,客戶端服務器僅僅負責提交計算任務給 Hadoop 集羣,並當 Hadoop 集羣完成任務後,客戶端服務器來拿走計算結果。在一個較小的集羣中(40個節點左右),可能一臺服務器會扮演多個角色,例如通常我們會將 Name Node 與 Job Tracker安置在同一臺服務器上。(由於 Name Node對內存開銷非常大,因此不贊成將 Name Node 與 Secondary Name Node 安置在同一臺機器上)。而在一個大型的集羣中,請無論如何要保證這三者分屬於不同的機器。

       在真實的集羣環境中,Hadoop 最好運行在 Linux 服務器上。當然,Hadoop 也可以運行在虛擬機中,但是,這僅僅是用來學習的一種方法,而不能將其用在生產環境中。
看懂Hadoop集羣原理與實現方式
       上圖是一個典型的 Hadoop 集羣架構。這張圖中,Hadoop 集羣以機架爲單位存在(而不是刀片機),而每個機架頂部都會有一個交換機通過千兆網與外部關聯,如果你的服務器比較給力,請確保帶寬足夠數據的傳輸以免帶寬影響運算(例如萬兆以太網)。我們通過上行鏈路將所有的機架鏈接在一起形成一個集羣。在一個機架中,有些服務器作爲 Master 節點,例如 Name Node等等,而更多的則是 Slave Node。

        到這裏,我們沒有討論更加詳細的設計方案,我們暫且放在一邊,下面開始看看程序是如何運行的。
  • 從集羣中加載數據(HDFS writes)
  • 分析數據(Map Reduce)
  • 在集羣中爲結果排序(HDFS writes)
  • 從集羣運算中讀取結果(HDFS reads)
應用場景:

        每天都有海量的郵件被客服收到,但是我怎麼才能知道這些郵件中究竟有多少郵件包含了“退款”這個詞?

        Hadoop 的存在價值是什麼?Hadoop 解決的是哪些問題?簡單來講,大型企業和政府都可能會包含有大量數據, (我們可以看做是一塊巨大的豆腐)例如馬路卡口監控視頻拍攝的機動車號牌,我們如果要對如此海量的數據進行復雜的分析,還要非常快速的得到結果,如果使用一臺計算機,根本無法勝任這個工作。如果能將這個龐然大物分割成許多小的數據塊,並將其分發給許許多多的服務器來協同計算,那麼這個效率自然是很快的,所以,Hadoop 的存在價值就體現在這裏。

        例如上面那個郵件的例子,經過日積月累,我們的服務器存有大量的郵件,我們可以將這些郵件打包成文本發送給Hadoop 集羣,只需要編寫一個簡單的計算單詞量的函數,並提交給集羣,集羣通過相互協調,在短時間內計算完畢之後返回一個結果。我就可以得到我想要的結果了。
看懂Hadoop集羣原理與實現方式
       Hadoop 集羣有了數據之後,便開始工作。我們在此的目的是大量數據的快速並行處理,爲了實現這個目標,我們應當利用儘可能多的機器,爲此,客戶端需要將數據分揀分成較小的塊,然後將這些快在集羣中不同的機器上並行計算。但是,這些服務器中的某些服務器可能會出現故障,因此,應當將每個數據塊做幾次拷貝,以確保數據不會被丟失。默認的拷貝次數是3次,但是我們可以通過 hdfs-site.xml 配置文件中 dfs.replication 這個參數來控制拷貝次數。

        客戶端將 File.txt 切割成三塊,並與Name Node協調,Name Node告知客戶端將這些數據分發到哪些 Data Node 上,收到數據塊的 Data Node 將會對收到的數據塊做幾次複製分發給其他的 Data Node 讓其他的 Data Node 也來計算同樣的數據(確保數據完整性)。此時,Name Node 的作用僅僅是負責管理數據,例如:哪些數據塊正在哪個Data Node上計算,以及這些數據將會運行到哪裏。(文件系統的元數據信息)
看懂Hadoop集羣原理與實現方式

        Hadoop 有“機架意識”的概念,作爲 Hadoop 的管理者,你可以手動的在你的集羣中爲每一個Slave Data Node定義機架號。你可能會問,我爲什麼要做這個工作?這裏有兩個關鍵點:數據丟失防護以及網絡性能。

        記住,每一個數據塊將會被複制到多態服務器上以確保數據不會因某個服務器的宕機而造成數據丟失,但是如果不幸的是,所有的拷貝都存放於一臺機架上,而這個機架由於種種原因造成了整個機架與外部斷開連接或整體宕機。例如一個嚴重的錯誤:交換機損壞。因此,爲了避免這種情況的發生,需要有人知道每一個 Data Node 在整個網絡拓撲圖中的位置,並智能的將數據分配到不同的機架中。這個就是 Name Node 的作用所在。

        還有一種假設,即兩臺機器在同一個機架和分屬於不同的機架比起來有更好的帶寬和更低的延遲。機架交換機上行鏈路帶寬通常比下行帶寬更少,此外,在機架內延遲通常比機架外的延遲要底。如果 Hadoop 有了相同機架優化的意識(提高網絡性能),同時能夠保護數據,這不是很酷嗎?
看懂Hadoop集羣原理與實現方式
        這裏的客戶端已經準備好將 FILE.txt 分成三塊添加到集羣中。客戶端會先告訴 Name Node 它將要把數據寫入到集羣中,從 Name Node處得到允許後,並受到 Name Node 爲其分配的 Data Node 清單,Name Node分配 Data Node 的時候會有一個智能決策的步驟,以默認的拷貝次數來講(3次), Name Node 會將其中兩個副本放在同一個機架中,而剩下的一個副本會放在另外一個機架中,並將分配結果告訴給客戶端,客戶端將會遵循這個分配結果將數據分配給三個 Data Node。

        當客戶端接收到 Name Node 給出的任務分配清單後,開始將數據傳輸給 Data Node,例如:Client 選擇 Block A 打開 TCP 50010 端口,告訴 Data Node 1 說:“嘿,給你一個數據塊 Block A,然後你去確保 Data Node 5 也準備好了,並讓它問問 Data Node 6 是不是也準備好了”。如此,Data Node們會通過TCP 50010 端口原路返回並逐層告知自己準備好了,最終讓客戶端得知清單上所列出的 Data Node 都準備好了。當客戶端得知都準備好之後,開始準備寫數據塊到集羣中。
看懂Hadoop集羣原理與實現方式

       數據塊被第一個 Data Node 接收後,會將其複製給下一個 Data Node 以此類推(複製次數由 dfs.replication 參數控制)。

        此處我們可以看到,Data Node 1 之所以在不同的機架上,是爲了避免數據丟失,而 Data Node 5 和 Data Node 6 存在於同一個機架是爲了保證網絡性能和低延遲。直到 Block A 被成功的寫入到第三個節點,Block B 纔會開始繼續寫入。
看懂Hadoop集羣原理與實現方式


        當所有的 Data Node 已經成功的接收到了數據塊,它們將會報告給 Name Node,同時也會告知客戶端一切準備就緒並關閉回話,此時客戶端也會返回一個成功的信息給 Name Node。Name Node 開始更新元數據信息將 Block A 在 File.txt 中的位置記錄下來。

        然後重複以上操作,直到剩下的兩個數據塊 Block B和 Block C 也分別寫入到其他的 Data Node 中。
看懂Hadoop集羣原理與實現方式
    通過以上步驟我們可以得知,如果我們有一個1TB的數據要做分析,那麼我們所佔用的網絡流量和磁盤空間將如下:

        使用流量= 磁盤空間 = dfs.replication*數據大小

        例如我們默認的設置是拷貝三次,那麼我們就需要消耗3TB的網絡流量和3TB的磁盤空間。
看懂Hadoop集羣原理與實現方式

        這樣,就如我們預期的那樣,將一個大的數據分割成無數小的數據提交給多個Data Node 進行並行計算。在這裏,我們可以通過橫向擴展增加服務器的數量來提高計算性能,但同時,網絡I/O 的吞吐也成爲了計算性能瓶頸之一,因爲如果橫向擴展,會給網絡吞吐帶來巨大的壓力,如何將 Hadoop 過渡到萬兆以太網是即將到來的難題。(而且北京這房價,擦擦擦……)

        還有一種方法則是通過提高單個 Data Node 的配置來提高計算性能。此爲縱向擴展。但通常不認爲這樣做是一個明智的選擇(除非您的機房費用真的很高)。
看懂Hadoop集羣原理與實現方式
        Name Node 在整個 HDFS 中處於關鍵位置,它保存了所有的文件系統的元數據信息用來監控每個 Data Node 的健康狀況。只有 Name Node 知道數據從哪裏來、將要被分配到哪裏去,最後返回給誰。

        Data Node 會每3秒鐘一次通過 TCP 9000端口發送心跳給 Name Node。每10次心跳生成一個健康報告,心跳數據都會包含關於該Data Node所擁有的數據塊信息。該報告讓 Name Node 知道不同的機架上不同的Data Node上存在的數據快的副本,併爲此建立元數據信息。

        Name Node的重要性不言而喻,沒有它,客戶端將不知道如何向HDFS寫入數據和讀取結果,就不可能執行 Map Reduce 工作,因此,Name Node 所在的服務器應當是一個比較牛逼的服務器(熱插拔風扇、冗餘網卡連接、雙電源等)。

        如果 Name Node 沒有接收到 Data Node 發送過來的心跳,那麼它將會假定該 Data Node 已經死亡。因爲有前面的心跳報告,因此 Name Node 知道該死亡的 Data Node 目前的工作內容以及進度,它將會將該 Data Node 所負責的內容分發給其他的 Data Node去完成。(同樣根據機架意識來分發該任務)。
看懂Hadoop集羣原理與實現方式

        Secondary Name Node 在國內通常被稱爲輔助 Name Node 因爲它並不是一個完整備份, Secondary Name Node 的存在雖然是爲了確保 Name Node 在宕機後能夠接手其職責,但是它與 Name Node 之間的元數據交互不是實時的。默認爲每隔一小時,Secondary Name Node 會主動請求 Name Node,並從 Name Node 中拿到文件系統的元數據信息(同步)。這個間隔可以通過配置項來設置。

        因此,如果萬一 Name Node 宕機,雖然 Secondary Name Node 能夠接手參加工作,但是依然會造成部分的數據丟失。因此,如果數據非常重要,默認的一小時同步一次可能遠遠不足以保護數據的計算進度,我們可以縮短其同步時間來增加數據的安全性例如:每分鐘同步一次。
看懂Hadoop集羣原理與實現方式

       當客戶端打算從 HDFS 中取數據的時候,例如一個作業的結果,同樣需要首先與 Name Node 打交道,的值想取的數據被存放在哪裏,Name Node 同樣會給客戶端一個清單,然後客戶端去 Name Node 指定的某個 Data Node 中拿數據(通過TCP 50010 端口)。

        客戶端不會逐個 Data Node 去拿數據,而是由 Name Node 指定的那個 Data Node 分別去其他的 Data Node 那裏拿數據。好像客戶端在說:“Name Node,告訴我數據都在哪兒?”,Name Node 說“他們在 Data Node x、y、z,你去 Data Node x 拿數據吧”,客戶端於是告訴 Data Node X,你把 y 和 z 的數據一起拿來並送到我這裏來。
看懂Hadoop集羣原理與實現方式
       還有一種情況,其中一個 Data Node 的守護進程本身將需要讀取HDFS的某些數據塊,例如Data Node 被要求來處理數據,但是他本地沒有,因此它必須從另一個數據節點中解鎖數據並通過網絡傳輸到本地開始處理。

        在這裏,Name Node 同樣會考慮“機架意識”,並通過機架意識來找到最近的 Data Node 並將數據傳輸過去。

        現在,我們已經知道 File.txt 被分發到不同的 Data Node上,也知道了他們是如何運轉的了,現在我們就開始看看 Hadoop 是具體如何使用 Map Reduce 框架來進行快速運算的吧。

        第一步是 Map 階段,在我們的例子中,我們要求我們的 Hadoop 集羣計算出郵件中“Refund”單詞的數量。

        在一開始,客戶端會提交一個 Map Reduce 作業,例如:“在 File.txt 中有多少個 Refund?”當然,這句話是翻譯自 Java 語言,通過 Java 編寫好一個 Map Reduce 作業並提交作業給 Job Tracker。Job Tracker 與 Name Node 協調得到哪些 Data Node 包含 File.txt 的數據塊。 然後 Job Tracker 開始在這些 Data Node 上激活 Task Tracker。 Task Tracker 開始 Map 作業並監視任務進度。Task Tracker同時也提供心跳和任務狀態給 Job Tracker。

        當所有的 Map 任務完成後,每個節點都會存放一個結果在其本地物理磁盤上,這被稱爲“中間數據”。接下來,就是將這些中間數據通過網絡發送給一個執行 Reduce 任務的節點。

看懂Hadoop集羣原理與實現方式
       Job Tracker 總會盡量挑選處理 Map 任務的節點來處理 Reduce 任務,因爲 Map 處理的數據就在本地,不需要通過網絡來傳輸,但是,Job Tracker 並不保證一定會挑選本地節點,因爲可能 Map 任務較多,沒有資源來運行 Reduce 任務,這樣,就會挑選其他的節點來完成 Reduce 任務。

        同樣,Job Tracker 會根據機架意識來挑選同一機架內的其他節點來完成 Reduce 任務。
看懂Hadoop集羣原理與實現方式
        第二步就是 Reduce,當 Map 生成了中間數據後,現在我們需要將所有的這些中間數據彙總計算生成最終的數據。

        Job Tracker 可能會挑選集羣中任意一個節點來作爲 Reduce 任務的處理服務器,此時可能會一次性有大量的數據涌向 Reduce 任務所在的節點服務器,這種情況通常被稱爲“Incast”或“fan-in”。這需要牛逼點的交換機以及內部流量管理和足夠的緩衝區(不要太大,也不要太小)。緩衝區的大小最終可能會造成不必要的附帶損害(流量相關)。但這是另外一個話題。

        現在 Reduce 已經收集到了所有從 Map 計算得到的中間數據,並可以開始最後階段的計算,在本文的例子中,我們僅僅是簡單的將各個結果相加即可得到“Refund”的數量。然後將結果寫入到 Results.txt 文件。客戶端可以從HDFS中讀取Results.txt 文件,並將工作視爲完成。

        這個例子並沒有造成大量的中間數據和流量佔用問題,但是實際生產環境可能會造成大量的中間數據和帶寬瓶頸。這就是 Map Reduce 作業中代碼如何計算的一門學問,如果用最優化的代碼來完成作業是需要我們來決定的。
看懂Hadoop集羣原理與實現方式
        如果在 Hadoop 集羣運算過程中添加了新的機架,那麼數據的負載均衡就成爲了一個問題所在,如何讓新增加的機架迅速的融入到計算環境中來成爲了一個很迫切的問題。
看懂Hadoop集羣原理與實現方式
        是的,Hadoop的確包含一個名爲 Balancer 的工具。Balancer作業與節點,並試圖提供計算平衡。但是默認的 Balancer 可利用的網絡帶寬是非常低的 1mb/s。不過此設置可以通過hdfs-site.xml 中的 dfs.balance.bandwidthPerSec 參數來設置。

        Balancer 可以很好的照顧你的集羣。鑑於 Balancer 的默認帶寬設置,他可能需要較長的時間來完成均衡的操作,可能幾天,也可能幾周。

原作者:Brad Hedlund
原文地址(英文):
http://bradhedlund.com/2011/09/10/understanding-hadoop-clusters-and-the-network/

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