HDFS 機架感知與副本放置策略
HDFS 機架感知與副本放置策略
機架感知(RackAwareness)
通常,大型 Hadoop 叢集會分佈在很多機架上,在這種情況下,
- 希望不同節點之間的通訊能夠儘量發生在同一個機架之內,而不是跨機架。
- 為了提高容錯能力,名稱節點會盡可能把資料塊的副本放到多個機架上。
綜合考慮這兩點的基礎上 Hadoop 設計了機架感知功能
外在指令碼實現機架感知
HDFS 不能夠自動判斷叢集中各個 DataNode 的網路拓撲情況。這種機架感知需要 net.topology.script.file.name 屬性定義的可執行檔案(或者指令碼)來實現,檔案提供了 DataNode 的IP 地址與機架 rackid 之間的對映關係。NameNode 通過這個對映關係,獲得叢集中各個 DataNode 機器的機架 rackid。如果 topology.script.file.name 沒有設定,則每個 DataNode 的 IP地址都會預設對映成 default-rack,即可同一個機架。
為了獲取機架 rackid,可以寫一個小指令碼來定義 DataNode 的 IP 地址(或DNS域名),並把想要的機架 rackid 列印到標準輸出 stdout
這個指令碼必須要在配置檔案 hadoop-site.xml 裡通過屬性 ’net.topology.script.file.name’ 來指定。
<property> <name>net.topology.script.file.name</name> <value>/root/apps/hadoop-3.2.1/topology.py</value> </property>
用 Python 語言編寫的指令碼範例:
內部Java類實現機架感知
該處採用配置 topology.node.switch.mapping.impl 來實現機架感知,需在 core-site.xml 配置檔案中加入以下配置項:
<property>
<name>topology.node.switch.mapping.impl</name>
<value>com.dmp.hadoop.cluster.topology.JavaTestBasedMapping</value>
</property>
還需編寫一個JAVA類,一個示例如下所示:
public class JavaTestBasedMapping implements DNSToSwitchMapping {
//key:ip value:rack
private staticConcurrentHashMap<String,String> cache = new ConcurrentHashMap<String,String>();
static {
//rack0 16
cache.put("192.168.5.116","/ht_dc/rack0");
cache.put("192.168.5.117","/ht_dc/rack0");
cache.put("192.168.5.118","/ht_dc/rack0");
cache.put("192.168.5.120","/ht_dc/rack0");
cache.put("192.168.5.121","/ht_dc/rack0");
cache.put("host116","/ht_dc/rack0");
cache.put("host117","/ht_dc/rack0");
cache.put("host118","/ht_dc/rack0");
cache.put("host120","/ht_dc/rack0");
cache.put("host121","/ht_dc/rack0");
}
@Override
publicList<String> resolve(List<String> names) {
List<String>m = new ArrayList<String>();
if (names ==null || names.size() == 0) {
m.add("/default-rack");
return m;
}
for (Stringname : names) {
Stringrack = cache.get(name);
if (rack!= null) {
m.add(rack);
}
}
return m;
}
}
將上述Java類打成jar包,加上執行許可權;然後放到$HADOOP_HOME/lib目錄下執行。
網路拓撲(NetworkTopology)
有了機架感知,NameNode 就可以畫出上圖所示的 DataNode 網路拓撲圖。D1,R1都是交換機,最底層是 DataNode。則H1 的 rackid=/D1/R1/H1,H1 的 parent 是R1,R1 的是 D1。這些機架 rackid 資訊可以通過 net.topology.script.file.name配置。有了這些機架 rackid 資訊就可以計算出任意兩臺 DataNode 之間的距離。
distance(/D1/R1/H1,/D1/R1/H1)=0 相同的datanode
distance(/D1/R1/H1,/D1/R1/H2)=2 同一rack下的不同datanode
distance(/D1/R1/H1,/D1/R1/H4)=4 同一IDC下的不同datanode
distance(/D1/R1/H1,/D2/R3/H7)=6 不同IDC下的datanode
副本放置策略(BPP:blockplacement policy)
- 第一個 block 副本放在和客戶端所在的 node 裡(如果client不在叢集範圍內,則這第一個node是隨機選取的,當然系統會嘗試不選擇哪些太滿或者太忙的node)。
- 第二個副本放置在與第一個節點不同的機架中的node中(隨機選擇)。
- 第三個副本和第二個在同一個機架,隨機放在不同的node中。
如果還有更多的副本,則在遵循以下限制的前提下隨機放置。
- 1個節點最多放置1個副本
- 如果副本數少於2倍機架數,不可以在同一機架放置超過2個副本
當發生資料讀取的時候,NameNode 節點首先檢查客戶端是否位於叢集中。如果是的話,就可以按照由近到遠的優先次序決定由哪個 DataNode 節點向客戶端傳送它需要的資料塊。也就是說,對於擁有同一資料塊副本的節點來說,在網路拓撲中距離客戶端近的節點會優先響應。
Hadoop 的副本放置策略在可靠性(block 在不同的機架)和頻寬(一個管道只需要穿越一個網路節點)中做了一個很好的平衡。
下圖是副本數量為3的情況下一個管道的三個 DataNode的分佈情況