Hadoop基礎-網絡拓撲機架感知及其實現
作者:尹正傑
版權聲明:原創作品,謝絕轉載!否則將追究法律責任。
一.網絡拓撲結構
在本地網絡中,兩個節點被稱為“彼此近鄰”是什么意思?在海量數據處理中,其主要限制因素是節點之間數據的傳輸速率,即帶寬稀缺。這里的想法是將兩個節點之間的帶寬作為距離的衡量標准。不用衡量節點之間的帶寬,實際上很難實現(它需要一個穩定的集群,並且在集群中兩兩節點對數量是節點數量的平方),hadoop為此采用了一個簡單的方法:把網絡看作一棵樹,兩個節點之間的距離是他們到最近共同祖先的距離總和。該樹中的層次是沒有預先設定的, 但是相對與數據中心,機架和正在運行的節點,通常可以設定等級。具體想法是針對以下每個常見,可用帶寬依次遞減:
1>.同一節點上的進程;
2>.同一機架上的不同節點;
3>.同一數據中心中不同機架上的節點;
4>.不同數據中心的節點‘
舉個例子,假設有數據中心d1,機架r1中的節點n1。該節點可以表示為“/d1/r1/n1”。利用這種標記,這里給出四種距離描述:
1>.distance(/d1/r1/n1,/d1/r1/n1)=0(同一節點上的進程);
2>.distance(/d1/r1/n1,/d1/r1/n2)=2(同一機架上的不同節點);
3>.distance(/d1/r1/n1,/d1/r2/n3)=4(同一數據中心中不同機架上的節點);
4>.distance(/d1/r1/n1,/d2/r3/n4)=6(不同數據中心中的節點);
上圖摘自《Hadoop權威指南第四版》。我們必須要意識到Hadoop無法自動發現你的網絡拓撲結構。它需要一些幫助,不過在默認情況下,假設網絡是扁平化的只有一層,換句話說,所有節點在同一數據中心的同一機架上。規模小的集群可能如此,不需要進一步配置。
二.機架感知
機架感知可以通過python和shell實現,詳情請參考官方文檔的案例:http://hadoop.apache.org/docs/r2.7.3/hadoop-project-dist/hadoop-common/RackAwareness.html。由於Hadoop是Java語言寫的,因此本篇博客主要使用Java代碼實現機架感知。在機架感知中,接受的數據(參數)是一個包含所有節點的ip或主機名的List,返回的數據也是一個List,是拓撲距離的list。
1>.編寫機架感知自定義邏輯代碼
1 /* 2 @author :yinzhengjie 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Hadoop%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/ 4 EMAIL:y1053419035@qq.com 5 */ 6 package cn.org.yinzhengjie.hdfs; 7 8 import org.apache.hadoop.net.DNSToSwitchMapping; 9 import java.util.ArrayList; 10 import java.util.List; 11 /** 12 *hadoop副本放置策略:(3副本情況) 13 * 1、在本地機架的一個節點放置一個副本 s101-s103 rack1 14 * 2、在其他機架的兩個結點放置兩個副本 s104-s105 rack2 15 */ 16 public class RackAware implements DNSToSwitchMapping { 17 public List<String> resolve(List<String> names) { 18 List<String> list = new ArrayList<String>(); 19 for(String name : names){ 20 Integer suffix = 0; 21 /** 22 * 第一種情況: names是主機名 23 */ 24 if(name.startsWith("s")){ 25 //將s101變為101 26 suffix = Integer.parseInt(name.substring(1)); 27 } 28 /** 29 * 第二種情況:names是ip 30 */ 31 else { 32 suffix = Integer.parseInt(name.substring(name.lastIndexOf(".") + 1)); 33 } 34 /** 35 * 我們的策略是主機位大於103的就放在第一個機會上,即"/rack1",否則就放在第二個機櫃上上,即"/rack2" 36 */ 37 if(suffix <= 103){ 38 // /rack1/s102 39 list.add("/rack1"); 40 } 41 else { 42 // /rack2/s105 43 list.add("/rack2"); 44 } 45 } 46 return list; 47 } 48 /** 49 * 下面的兩個方法空實現即可。不用搭理它們,咱們這里用不到他們兩個方法 50 */ 51 public void reloadCachedMappings() {} 52 public void reloadCachedMappings(List<String> names) {} 53 }
2>.打包並上傳至服務器端的/soft/hadoop/share/hadoop/common/lib目錄下
3>.修改配置文件
4>.分發配置文件
[yinzhengjie@s101 ~]$ more `which xrsync.sh` #!/bin/bash #@author :yinzhengjie #blog:http://www.cnblogs.com/yinzhengjie #EMAIL:y1053419035@qq.com #判斷用戶是否傳參 if [ $# -lt 1 ];then echo "請輸入參數"; exit fi #獲取文件路徑 file=$@ #獲取子路徑 filename=`basename $file` #獲取父路徑 dirpath=`dirname $file` #獲取完整路徑 cd $dirpath fullpath=`pwd -P` #同步文件到DataNode for (( i=102;i<=105;i++ )) do #使終端變綠色 tput setaf 2 echo =========== s$i %file =========== #使終端變回原來的顏色,即白灰色 tput setaf 7 #遠程執行命令 rsync -lr $filename `whoami`@s$i:$fullpath #判斷命令是否執行成功 if [ $? == 0 ];then echo "命令執行成功" fi done [yinzhengjie@s101 ~]$ [yinzhengjie@s101 ~]$ xrsync.sh /soft/hadoop/etc/hadoop/core-site.xml =========== s102 %file =========== 命令執行成功 =========== s103 %file =========== 命令執行成功 =========== s104 %file =========== 命令執行成功 =========== s105 %file =========== 命令執行成功 [yinzhengjie@s101 ~]$ xrsync.sh /soft/hadoop/etc/hadoop/slaves =========== s102 %file =========== 命令執行成功 =========== s103 %file =========== 命令執行成功 =========== s104 %file =========== 命令執行成功 =========== s105 %file =========== 命令執行成功 [yinzhengjie@s101 ~]$ [yinzhengjie@s101 ~]$ xrsync.sh /soft/hadoop/share/hadoop/common/lib/MyHbase-1.0-SNAPSHOT.jar =========== s102 %file =========== 命令執行成功 =========== s103 %file =========== 命令執行成功 =========== s104 %file =========== 命令執行成功 =========== s105 %file =========== 命令執行成功 [yinzhengjie@s101 ~]$
5>.啟動HDFS並查看NameNode日志