HDFS数据跨区域存储分布

文章目录

  • 前言
  • 跨区域存储和跨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数据跨区域存储分布_第1张图片
HDFS数据跨区域存储分布_第2张图片

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 scope.
   * @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 scope.
   *
   * If scope starts with ~, choose one from the all nodes except for the
   * ones in scope; otherwise, choose one from scope.
   * 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,Hadoop,hadoop,big,data)