文章目錄
- 前言
- 跨區域存盤和跨rack存盤的區別
- HDFS跨區域存盤代碼邏輯修改
前言
在上篇文章HDFS多rack分布的block placement policy設計實作里,筆者探討了HDFS資料副本跨多rack分布的新placement方案,以此來提高資料的可用性,因為在日常集群運行程序中,是可能存在因為集群的操作維護導致短時間內一整個rack處于停服務狀態的,按照HDFS三副本的存放策略,一整個rack離線意味著2/3的拷貝丟失了,這將極大增加資料不可訪問的概率,本文我們來繼續深入探討這一話題,既然資料副本已經能夠做到rack粒度的分開存盤,那么是否我們還能夠再進一步做到磁區域的存盤呢?這里的區域概念指的是一個集群內的各個區域,各個區域里之間具有一定隔離性,但是它們還是屬于一個data center,在一個data center內,如果我們還能將資料均勻分配到這些獨立區域內,這樣就不僅能夠做到rack的分離,還能做到區域的隔離了,這樣的話,我們的資料還能夠容忍一個區域機器的crash,這樣毫無疑問,能夠再次提高集群資料的可用性,本文我們就來聊聊資料的跨區域存盤,
跨區域存盤和跨rack存盤的區別
首先我們來具體解釋下跨區域和跨rack存盤的差別:
一個data center里,區域數量是比較少的,一個區域里包含一組rack,它是rack的集合,一個集群可以包含有幾個區域,我們可以理解這里的區域是一個zone的概念,不同區域可以互為災備,用更簡單的話來解釋,區域是rack上面更高一級的概念,我們假設rack不會出現同時包含在2個區域分布的情況下,那么跨區域的資料存盤也一定是跨rack的資料存盤,
下面分別是資料跨rack以及跨區域的分布效果圖:


HDFS跨區域存盤代碼邏輯修改
上篇文章筆者詳細分析了如何改動原有的choose target邏輯來支持3個rack location選擇,主要的操作是覆寫了其中chooseLocalRack的方法,將其轉成類似choose remote rack的邏輯,choose remote rack采用的是隨機rack選擇的方法,并沒有同時傳入之前選中的2個rack資訊,其中會存在一定小概率的rack被重復選中的可能,因此在location檢查的方法中多做了rack的判斷,
但是在資料跨區域存盤中,由于可選區域數遠比集群rack數少,因此倘若依然采用隨機選擇的辦法,將會導致一個比較高的區域重復選擇率,因此如何做到精準,高效的區域選擇,是一個需要重點解決的問題,
透過現象看本質,上面問題發生的原因實質上是所選location位置沒有作為exclude的位置資訊傳入,導致了后續location選擇的不精準,所以如果我們能把之前選過的location資訊傳入到后續的location選擇方法內,那么是否就能完美解決這個問題了呢?
這里我們要把HDFS choose target的邏輯搬出來,看看它是怎么跑的,在默認的block placement實作類中,我們能夠看到下面這樣的方法:
/**
* Choose a datanode from the given <i>scope</i>.
* @return the chosen node, if there is any.
*/
protected DatanodeDescriptor chooseDataNode(final String scope,
final Collection<Node> excludedNodes) {
return (DatanodeDescriptor) clusterMap.chooseRandom(scope, excludedNodes);
}
然后后面呼叫到的是NetworkTopology的chooseRandom方法,
/**
* Randomly choose one node from <i>scope</i>.
*
* If scope starts with ~, choose one from the all nodes except for the
* ones in <i>scope</i>; otherwise, choose one from <i>scope</i>.
* If excludedNodes is given, choose a node that's not in excludedNodes.
*
* @param scope range of nodes from which a node will be chosen
* @param excludedNodes nodes to be excluded from
* @return the chosen node
*/
public Node chooseRandom(final String scope,
final Collection<Node> excludedNodes) {
netlock.readLock().lock();
try {
if (scope.startsWith("~")) {
return chooseRandom(NodeBase.ROOT, scope.substring(1), excludedNodes);
} else {
return chooseRandom(scope, null, excludedNodes);
}
} finally {
netlock.readLock().unlock();
}
}
從上面我們可以看到,方法引數里的scope值其實表明的就是一個exclude的位置資訊,在choose remote rack的邏輯方法里,這個scope傳入的值是‘"~" + localMachine.getNetworkLocation()’, ~代表的意思是相反的意思,意為除localMachine所在rack之外的一個scope,
protected void chooseRemoteRack(int numOfReplicas,
DatanodeDescriptor localMachine,
Set<Node> excludedNodes,
long blocksize,
int maxReplicasPerRack,
List<DatanodeStorageInfo> results,
boolean avoidStaleNodes,
EnumMap<StorageType, Integer> storageTypes)
throws NotEnoughReplicasException {
int oldNumOfReplicas = results.size();
// randomly choose one node from remote racks
try {
chooseRandom(numOfReplicas, "~" + localMachine.getNetworkLocation(),
excludedNodes, blocksize, maxReplicasPerRack, results,
avoidStaleNodes, storageTypes);
} catch (NotEnoughReplicasException e) {
....
}
}
因此如果我們想支持跨區域的location選擇,我們勢必要在這個scope上做些文章,我們需要在引數上再加上一個scope,這樣后續邏輯在選擇location的時候能夠exclude掉指定的區域資訊,新的choose target類似如下所示:
private Node chooseRandom(final String scope, String excludedScope,
String secondExcludedScope, final Collection<Node> excludedNodes) {
...
}
在使用新的方法時,我們可以傳入2個區域資訊作為exclude的位置資訊,這樣能直接選出第三區域的有效location,樣例如下:
Node random = cluster.chooseRandomWithExcludeScope("~" + "/d1", "~" + "/d2", null);
public Node chooseRandomWithExcludeScope(final String excludeScope,
final String secondExcludeScope, final Collection<Node>excludedNodes) {
netlock.readLock().lock();
try {
return chooseRandom(NodeBase.ROOT, excludeScope.substring(1),
secondExcludeScope.substring(1), excludedNodes);
} finally {
netlock.readLock().unlock();
}
}
上面的改動會涉及到底層NetworkTopology類的改動,除此之外,其它的邏輯可以復用上篇文章所講述的跨rack location選擇的邏輯改動,
采用上述新的placement策略后,資料在一個data center跨區域進行存盤后,它能夠比之前跨rack的方式具有更高的可用性,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/301705.html
標籤:其他
上一篇:一起重新開始學大資料-Hbase篇-day 57 Hbase調優
下一篇:手撕三種分布式鎖
