Hadoop作為大數據處理的典型平台,在海量數據處理過程中,其主要限制因素是節點之間的數據傳輸速率。因為集群的帶寬有限,而有限的帶寬資源卻承擔着大量的剛性帶寬需求,例如Shuffle階段的數據傳輸不可避免,所以如何優化帶寬資源的占用是一個值得思考的問題。仔細思考下,Hadoop數據傳輸的需求主要表現在幾個方面:
- Map階段的數據傳輸:Map階段的非本地化任務需要遠程拷貝數據塊,然而這種帶寬消耗在一定程度上不是必要的,如果數據能做到很高程度的本地化可以減少這個階段的數據傳輸帶來的帶寬消耗。
- Shuffle階段的數據傳輸:Map階段的中間數據集需要傳輸到Reduce端需要大量的帶寬資源。
- Reduce階段的計算結果保存:Reduce端最終的計算結果需要保存到HDFS上,這種帶寬的消耗也是不可避免的。
不過還好,Hadoop的設計者們在最初就考慮到了這個問題,所以在Map階段的任務調度過程中做了一定程度的優化。當一個有空閑資源的TT(TaskTracker)向JT(JobTracker)申請任務的時候,JT會選擇一個最靠近TT的任務給它,選擇的原則是:
- TT本地是否有未處理的任務,有則調度之;
- TT本地沒有未處理的任務,則調度一個和TT同一個機架上的任務給它;
- 否則,調度一個本數據中心的任務給他。
然而,我們會思考JT使如何知道這種結構關系的呢?為啥就知道另一個節點就是和這個TT是同一個機架或者數據中心的呢?這就要追溯到Hadoop的機架感知功能了。
- 什么是機架感知
機架感知是一種計算不同計算節點(TT)的距離的技術,用以在任務調度過程中盡量減少網絡帶寬資源的消耗,這里用盡量,想表達的是當一個TT申請不到本地化任務時,JT會盡量調度一個機架的任務給他,因為不同機架的網絡帶寬資源比同一個機架的網絡帶寬資源更可貴。當然,機架感知不僅僅用在MR中,同樣還用在HDFS數據塊備份過程中(第一個replica選擇本節點【如果上傳是DataNode】或者隨機的一個DN(系統會盡量避免存儲太滿和太忙的節點),第二個節點選擇於第一個節點不同機架的DN,第三個選擇放在第二個DN同一個機架的另一個DN上)
- 機架感知實戰
首先,看下面這個圖的一個集群結構,D1和D2是兩個數據中心,下面各有兩個機架,然后葉子節點是DN。
此時H1和H2是同一個Rack的,H1和H4是同一個數據中心的。而H1和H7是不同數據中心的。
然而,上面這種樹結構不是Hadoop自己就自動建立的,需要用戶的手動設置協助。在小型的集群中和單機測試中,一般是用不着配置的,所以機架感知功能默認是關閉的。
要設置機架感知,用戶需要自己編寫腳本來定義節點的映射關系和配置conf/core-site.xml文件的屬性來啟動機架感知。
一個腳本實例程序如下面的例子所示,定義了一個rack字典,里面有每個hostname對應的rack信息,后面也給出了每個IP對應的rack信息。將這段腳本程序放在每個節點的hadoop/bin/目錄下,包括主節點。
#!/usr/bin/python #-*-coding:utf-8 -*- import sys rack = { "brix-01":"rack1", "brix-02":"rack1", "brix-03":"rack1", "brix-04":"rack1", "brix-05":"rack1", "brix-06":"rack1", "brix-07":"rack1", "brix-08":"rack1", "brix-09":"rack1", "192.168.1.231":"rack1", "192.168.1.232":"rack1", "192.168.1.233":"rack1", "192.168.1.234":"rack1", "192.168.1.235":"rack1", "192.168.1.236":"rack1", "192.168.1.237":"rack1", "192.168.1.238":"rack1", "192.168.1.239":"rack1" } if __name__=="__main__": print "/"+rack.get(sys.argv[1],"rack0")
寫好腳本程序后,然后配置core-site.xml文件,添加如下屬性:
<property> <name>topology.script.file.name</name> <value>/home/hadoop/hadoop/bin/RackAware.py</value> </property> <property> <name>topology.script.number.args</name> <value>18</value> </property>
在第一次,故意將腳本程序寫錯,發現啟動集群后觀察日志發現接收到heartbeat信息后會報錯,這說明,JT在得知啟動機架感知后,在收到TT的心跳信息后會將其地址作為參數傳入腳本,找到其對應的rack,然后將這些信息保存到內存中。
2014-11-17 21:15:24,658 INFO org.apache.hadoop.mapred.JobTracker: Lost tracker 'tracker_brix-03:localhost/127.0.0.1:39733'
2014-11-17 21:15:24,658 INFO org.apache.hadoop.ipc.Server: IPC Server handler 4 on 19001, call heartbeat(org.apache.hadoop.mapred.TaskTrackerStatus@47d2a09d, true, true, true, -1) from 192.168.1.236:53534:
error: java.io.IOException: java.lang.NullPointerException
java.io.IOException: java.lang.NullPointerException
at org.apache.hadoop.mapred.JobTracker.resolveAndAddToTopology(JobTracker.java:2385)
at org.apache.hadoop.mapred.JobTracker.addNewTracker(JobTracker.java:2377)
at org.apache.hadoop.mapred.JobTracker.processHeartbeat(JobTracker.java:2756)
at org.apache.hadoop.mapred.JobTracker.heartbeat(JobTracker.java:2556)
at sun.reflect.GeneratedMethodAccessor6.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.apache.hadoop.ipc.RPC$Server.call(RPC.java:508)
at org.apache.hadoop.ipc.Server$Handler$1.run(Server.java:959)
at org.apache.hadoop.ipc.Server$Handler$1.run(Server.java:955)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:422)
at org.apache.hadoop.ipc.Server$Handler.run(Server.java:954)
2014-11-17 21:15:24,677 WARN org.apache.hadoop.net.ScriptBasedMapping: org.apache.hadoop.util.Shell$ExitCodeException: File "/home/hadoop/hadoop/bin/RackAware.py", line 6
"brix-02":"rack1"
^
SyntaxError: invalid syntax
2014-11-17 21:20:05,848 INFO org.apache.hadoop.mapred.JobTracker: Starting RUNNING
2014-11-17 21:20:05,858 INFO org.apache.hadoop.ipc.Server: IPC Server handler 9 on 19001: starting
2014-11-17 21:20:05,985 INFO org.apache.hadoop.net.NetworkTopology: Adding a new node: /rack1/brix-02
2014-11-17 21:20:06,012 INFO org.apache.hadoop.net.NetworkTopology: Adding a new node: /rack1/brix-03
2014-11-17 21:20:06,037 INFO org.apache.hadoop.net.NetworkTopology: Adding a new node: /rack1/brix-01
2014-11-17 21:20:06,078 INFO org.apache.hadoop.net.NetworkTopology: Adding a new node: /rack1/brix-04
2014-11-17 21:20:06,099 INFO org.apache.hadoop.net.NetworkTopology: Adding a new node: /rack1/brix-07
2014-11-17 21:20:06,127 INFO org.apache.hadoop.net.NetworkTopology: Adding a new node: /rack1/brix-08
2014-11-17 21:20:06,151 INFO org.apache.hadoop.net.NetworkTopology: Adding a new node: /rack1/brix-09
2014-11-17 21:20:06,173 INFO org.apache.hadoop.net.NetworkTopology: Adding a new node: /rack1/brix-05
2014-11-17 21:20:06,193 INFO org.apache.hadoop.net.NetworkTopology: Adding a new node: /rack1/brix-06
配置正確后,啟動集群觀察JT的日志發現建立了機架的拓撲關系了。