HDFS的副本存放策略(机架感知策略)
HDFS作為Hadoop中的一個分布式文件系統(tǒng),而且是專門為它的MapReduce設(shè)計,所以HDFS除了必須滿足自己作為分布式文件系統(tǒng)的高可靠性外,還必須為MapReduce提供高效的讀寫性能,那么HDFS是如何做到這些的呢?首先,HDFS將每一個文件的數(shù)據(jù)進行分塊存儲,同時每一個數(shù)據(jù)塊又保存有多個副本,這些數(shù)據(jù)塊副本分布在不同的機器節(jié)點上,這種數(shù)據(jù)分塊存儲+副本的策略是HDFS保證可靠性和性能的關(guān)鍵,這是因為:一.文件分塊存儲之后按照數(shù)據(jù)塊來讀,提高了文件隨機讀的效率和并發(fā)讀的效率;二.保存數(shù)據(jù)塊若干副本到不同的機器節(jié)點實現(xiàn)可靠性的同時也提高了同一數(shù)據(jù)塊的并發(fā)讀效率;三.數(shù)據(jù)分塊是非常切合MapReduce中任務(wù)切分的思想。在這里,副本的存放策略又是HDFS實現(xiàn)高可靠性和搞性能的關(guān)鍵。
? HDFS采用一種稱為機架感知的策略來改進數(shù)據(jù)的可靠性、可用性和網(wǎng)絡(luò)帶寬的利用率。通過一個機架感知的過程,NameNode可以確定每一個DataNode所屬的機架id(這也是NameNode采用NetworkTopology數(shù)據(jù)結(jié)構(gòu)來存儲數(shù)據(jù)節(jié)點的原因,也是我在前面詳細介紹NetworkTopology類的原因)。一個簡單但沒有優(yōu)化的策略就是將副本存放在不同的機架上,這樣可以防止當整個機架失效時數(shù)據(jù)的丟失,并且允許讀數(shù)據(jù)的時候充分利用多個機架的帶寬。這種策略設(shè)置可以將副本均勻分布在集群中,有利于當組件失效的情況下的均勻負載,但是,因為這種策略的一個寫操作需要傳輸?shù)蕉鄠€機架,這增加了寫的代價。
在大多數(shù)情況下,副本系數(shù)是3,HDFS的存放策略是將一個副本存放在本地機架節(jié)點上,一個副本存放在同一個機架的另一個節(jié)點上,最后一個副本放在不同機架的節(jié)點上。這種策略減少了機架間的數(shù)據(jù)傳輸,提高了寫操作的效率。機架的錯誤遠遠比節(jié)點的錯誤少,所以這種策略不會影響到數(shù)據(jù)的可靠性和可用性。與此同時,因為數(shù)據(jù)塊只存放在兩個不同的機架上,所以此策略減少了讀取數(shù)據(jù)時需要的網(wǎng)絡(luò)傳輸總帶寬。在這種策略下,副本并不是均勻的分布在不同的機架上:三分之一的副本在一個節(jié)點上,三分之二的副本在一個機架上,其它副本均勻分布在剩下的機架中,這種策略在不損害數(shù)據(jù)可靠性和讀取性能的情況下改進了寫的性能。下面就來看看HDFS是如何來具體實現(xiàn)這一策略的。
? NameNode是通過類來為每一分數(shù)據(jù)塊選擇副本的存放位置的,這個ReplicationTargetChooser的一般處理過程如下:
上面的流程圖詳細的描述了Hadoop-0.2.0版本中副本的存放位置的選擇策略,當然,這當中還有一些細節(jié)問題,如:如何選擇一個本地數(shù)據(jù)節(jié)點,如何選擇一個本地機架數(shù)據(jù)節(jié)點等,所以下面我還將繼續(xù)展開討論。
1.選擇一個本地節(jié)點
這里所說的本地節(jié)點是相對于客戶端來說的,也就是說某一個用戶正在用一個客戶端來向HDFS中寫數(shù)據(jù),如果該客戶端上有數(shù)據(jù)節(jié)點,那么就應(yīng)該最優(yōu)先考慮把正在寫入的數(shù)據(jù)的一個副本保存在這個客戶端的數(shù)據(jù)節(jié)點上,它即被看做是本地節(jié)點,但是如果這個客戶端上的數(shù)據(jù)節(jié)點空間不足或者是當前負載過重,則應(yīng)該從該數(shù)據(jù)節(jié)點所在的機架中選擇一個合適的數(shù)據(jù)節(jié)點作為此時這個數(shù)據(jù)塊的本地節(jié)點。另外,如果客戶端上沒有一個數(shù)據(jù)節(jié)點的話,則從整個集群中隨機選擇一個合適的數(shù)據(jù)節(jié)點作為此時這個數(shù)據(jù)塊的本地節(jié)點。那么,如何判定一個數(shù)據(jù)節(jié)點合不合適呢,它是通過isGoodTarget方法來確定的:
2.選擇一個本地機架節(jié)點
實際上,選擇本地節(jié)假節(jié)點和遠程機架節(jié)點都需要以一個節(jié)點為參考,這樣才是有意義,所以在上面的流程圖中,我用紅色字體標出了參考點。那么,ReplicationTargetChooser是如何根據(jù)一個節(jié)點選擇它的一個本地機架節(jié)點呢?
這個過程很簡單,如果參考點為空,則從整個集群中隨機選擇一個合適的數(shù)據(jù)節(jié)點作為此時的本地機架節(jié)點;否則就從參考節(jié)點所在的機架中隨機選擇一個合適的數(shù)據(jù)節(jié)點作為此時的本地機架節(jié)點,若這個集群中沒有合適的數(shù)據(jù)節(jié)點的話,則從已選擇的數(shù)據(jù)節(jié)點中找出一個作為新的參考點,如果找到了一個新的參考點,則從這個新的參考點在的機架中隨機選擇一個合適的數(shù)據(jù)節(jié)點作為此時的本地機架節(jié)點;否則從整個集群中隨機選擇一個合適的數(shù)據(jù)節(jié)點作為此時的本地機架節(jié)點。如果新的參考點所在的機架中仍然沒有合適的數(shù)據(jù)節(jié)點,則只能從整個集群中隨機選擇一個合適的數(shù)據(jù)節(jié)點作為此時的本地機架節(jié)點了。
3.選擇一個遠程機架節(jié)點
選擇一個遠程機架節(jié)點就是隨機的選擇一個合適的不在參考點坐在的機架中的數(shù)據(jù)節(jié)點,如果沒有找到這個合適的數(shù)據(jù)節(jié)點的話,就只能從參考點所在的機架中選擇一個合適的數(shù)據(jù)節(jié)點作為此時的遠程機架節(jié)點了。
4.隨機選擇若干數(shù)據(jù)節(jié)點
這里的隨機隨機選擇若干個數(shù)據(jù)節(jié)點實際上指的是從某一個范圍內(nèi)隨機的選擇若干個節(jié)點,它的實現(xiàn)需要利用前面提到過的NetworkTopology數(shù)據(jù)結(jié)構(gòu)。隨機選擇所使用的范圍本質(zhì)上指的是一個路徑,這個路徑表示的是NetworkTopology所表示的樹狀網(wǎng)絡(luò)拓撲圖中的一個非葉子節(jié)點,隨機選擇針對的就是這個節(jié)點的所有葉子子節(jié)點,因為所有的數(shù)據(jù)節(jié)點都被表示成了這個樹狀網(wǎng)絡(luò)拓撲圖中的葉子節(jié)點。
5.優(yōu)化數(shù)據(jù)傳輸?shù)穆窂?br /> 以前說過,HDFS對于Block的副本copy采用的是流水線作業(yè)的方式:client把數(shù)據(jù)Block只傳給一個DataNode,這個DataNode收到Block之后,傳給下一個DataNode,依次類推,…,最后一個DataNode就不需要下傳數(shù)據(jù)Block了。所以,在為一個數(shù)據(jù)塊確定了所有的副本存放的位置之后,就需要確定這種數(shù)據(jù)節(jié)點之間流水復制的順序,這種順序應(yīng)該使得數(shù)據(jù)傳輸時花費的網(wǎng)絡(luò)延時最小。ReplicationTargetChooser用了非常簡單的方法來考量的,大家一看便知:
1. **private DatanodeDescriptor[] getPipeline( DatanodeDescriptor writer, DatanodeDescriptor[] nodes) {** 2. **if (nodes.length==0) \**return nodes;\**** 3. ? 4. **synchronized(clusterMap) {** 5. **int index=0;** 6. **if (writer == \**null || !clusterMap.contains(writer)) {\**** 7. ? writer = nodes[0]; 8. } 9. ? 10. **for(;index<nodes.length; index++) {** 11. ? DatanodeDescriptor shortestNode = nodes[index]; 12. ? **int shortestDistance = clusterMap.getDistance(writer, shortestNode);** 13. ? **int shortestIndex = index;** 14. ? **for(\**int i=index+1; i<nodes.length; i++) {\**** 15. ? DatanodeDescriptor currentNode = nodes[i]; 16. ? **int currentDistance = clusterMap.getDistance(writer, currentNode);** 17. ? **if (shortestDistance>currentDistance) {** 18. ? shortestDistance = currentDistance; 19. ? shortestNode = currentNode; 20. ? shortestIndex = i; 21. ? } 22. ? } 23. ? //switch position index & shortestIndex 24. ? **if (index != shortestIndex) {** 25. ? nodes[shortestIndex] = nodes[index]; 26. ? nodes[index] = shortestNode; 27. ? } 28. ? writer = shortestNode; 29. } 30. } 31. **return nodes;** 32. }可惜的是,HDFS目前并沒有把副本存放策略的實現(xiàn)開放給用戶,也就是用戶無法根據(jù)自己的實際需求來指定文件的數(shù)據(jù)塊存放的具體位置。例如:我們可以將有關(guān)系的兩個文件放到相同的數(shù)據(jù)節(jié)點上,這樣在進行map-reduce的時候,其工作效率會大大的提高。但是,又考慮到副本存放策略是與集群負載均衡休戚相關(guān)的,所以要是真的把負載存放策略交給用戶來實現(xiàn)的話,對用戶來說是相當負載的,所以我只能說Hadoop目前還不算成熟,尚需大踏步發(fā)展。
總結(jié)
以上是生活随笔為你收集整理的HDFS的副本存放策略(机架感知策略)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: docker-compose部署kafk
- 下一篇: 【收藏】keepalived配置文件解读