版本:Apache Hadoop 1.0.3
Hadoop集羣節點通常會跨很多個機架,增加節點的情況時有發生,而且很多時候節點的磁盤容量還不統一,有大有小,所以集羣節點非常容易出現磁盤利用不平衡的情況,一些節點的磁盤快用光了,另外一些節點磁盤容量還剩餘很多。這會導致一些問題,首先是一些機器磁盤讀寫很頻繁,另外一些機器很閒;MR任務分配到一個沒有相應數據塊的節點上時,需要從其它機器上拿數據,佔用大量的網絡帶寬,又拖慢了任務執行的時間。
如何儘量避免這些情況的發生呢?首先要配置機架感知,把一部分數據分配到其它機架內的節點上;即使這樣還不夠,仍然會出現不數據存放不平衡的現象,我們還需要balancer。
balancer的話,可以使用命令bin/start-balancer.sh -threshold N。
balancer過程有點複雜,但是有一點,再平衡時會優先考慮同一機架內的節點。例如有兩個機架,機架1和機架2,其中節點A位於機架1內,當集羣再平衡時,系統會優先把節點A的數據塊平衡到機架1中的其它節點,而不是機架2的節點。這樣,當再平衡結束時,會導致數據塊在整個HDFS集羣中的分佈仍然不平衡。所以在建設Hadoop集羣時應該考慮到這個情況,最好把磁盤容量大的節點和磁盤容量小的節點混合安排進一個機架。
我們重點來看機架感知。
Hadoop在設計時考慮到數據的安全與高效,數據文件默認在HDFS上存放三份,存儲策略爲本地一份,同機架內其它某一節點上一份,不同機架的某一節點上一份。這樣如果本地數據損壞,節點可以從同一機架內的相鄰節點拿到數據,速度肯定比從跨機架節點上拿數據要快;同時,如果整個機架的網絡出現異常,也能保證在其它機架的節點上找到數據。
那麼Hadoop是如何確定任意兩個節點是位於同一機架,還是跨機架的呢?答案就是機架感知。
HDFS集羣在啓動時會檢查機架感知配置,根據配置對節點進行一次掃描轉換,得到節點的機架ID,相同ID的節點肯定位於同一機架。問題是,Hadoop並不能智能識別節點位於哪個機架,它需要我們告訴集羣哪些節點屬於哪些機架,然後集羣才能得到這些節點的機架ID。我們需要配置一下,使機架感知生效。
在core-site.xml中有一個參數,topology.script.file.name,該參數通常指定一個腳本,用來輸出節點與機架的對應關係。最簡單的示例是hadoop wiki中的一個腳本,參考:http://wiki.apache.org/hadoop/topology_rack_awareness_scripts。
#!/bin/bash HADOOP_CONF=/etc/hadoop/conf while [ $# -gt 0 ] ; do nodeArg=$1 exec< ${HADOOP_CONF}/topology.data result="" while read line ; do ar=( $line ) if [ "${ar[0]}" = "$nodeArg" ] ; then result="${ar[1]}" fi done shift if [ -z "$result" ] ; then echo -n "/default/rack " else echo -n "$result " fi done
topology.data的格式爲:節點(ip或主機名) /交換機xx/機架xx
需要注意的是,在Namenode上,該文件中的節點必須使用IP,使用主機名無效,而Jobtracker上,該文件中的節點必須使用主機名,使用IP無效。這經過了本人的親自試驗。