HDFS数据跨区域存储分布
Posted Android路上的人
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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的方式具有更高的可用性。
以上是关于HDFS数据跨区域存储分布的主要内容,如果未能解决你的问题,请参考以下文章