HDFS多rack分布的block placement policy设计实现

前言


众所周知,HDFS拥有3副本来保证其数据的高可用性。而且HDFS对着三个副本的位置放置也是有专心设计的,2个副本放在同一个rack(不同节点),另外一个副本放在另外的一个rack上。在这样的放置策略下,这个副本数据能容忍一个节点的crash甚至是一个rack机器的crash。但这里所提及的"rack“的概念是集群admin给HDFS定义的rack的概念,它是一个逻辑上的概念。它可以简单的是一个物理rack,也可以是一组rack的集合。不过它们一个共同的特征是rack与rack之间是能够隔离开的。HDFS目前默认的block放置策略在理论上是能够容忍一个rack的掉线,但是在实际大规模集群的运行过程中,默认的放置策略还是不能够完全保证数据高可用性的要求。举例来说,笔者最近在生产集群上频繁碰到因为数据3副本同时不可用导致的用户missing block问题。后来发现是因为集群在进行按rack的rolling升级,每次会有长达1小时的rack shutdown的时间。然后在此期间,偶发的其它rack的机器的dead,就会造成这种零星的missing block情况。这个问题本质上的原因是因为掉了1个rack,导致存在于此rack上的2副本无法使用,进而导致了大概率数据无法使用的情况。针对此情况,我们尝试对现有的block placement策略进行改造,来解决这个问题。

HDFS多rack分布的block placement policy


我们知道,HDFS的block位置存放一方面是基于内部的block placement policy实现,还有另一方面是admin给定的topology设置。Topology是这里的作用是规定了什么节点属于哪些rack。

如果我们不想对现有HDFS placement policy进行改造来解决上面提到的问题,改变集群使用的topology也是能够奏效的。让topology里的rack映射到实际更多的物理rack能一定程度上减缓这个问题。但这里笔者说的是减缓,不是彻底解决。因为topology里的rack的scope尽管变大了,但是还是存在俩副本落在一个物理rack上的情况的。

因此,从根本上解决block按照rack分布的问题的办法就是改变其block placement的policy策略来做。目标期望的block placement分布也很简单,就是3副本同时分布在3个rack上。这样的话,集群就能够极大地容忍一个rack掉线导致的数据不可用问题。

多rack分布的policy实现思路


鉴于HDFS默认的block placement policy实现逻辑比较复杂,我们不倾向于直接改它里面的过程逻辑。而是新增一个新的policy类,然后覆盖其部分方法,以此来达到我们按照rack分布的block placement policy的实现。

我们先来看看默认的block placement policy的核心方法,BlockPlacementPolicyDefault#chooseTarget方法:

  private Node chooseTarget(int numOfReplicas,
                            Node writer,
                            final Set<Node> excludedNodes,
                            final long blocksize,
                            final int maxNodesPerRack,
                            final List<DatanodeStorageInfo> results,
                            final boolean avoidStaleNodes,
                            final BlockStoragePolicy storagePolicy,
                            final EnumSet<StorageType> unavailableStorages,
                            final boolean newBlock) {
   
    if (numOfReplicas == 0 || clusterMap.getNumOfLeaves()==0) {
   
      return (writer instanceof DatanodeDescriptor) ? writer : null;
    }
    final int numOfResults = results.size();
    final int totalReplicasExpected = numOfReplicas + numOfResults;
    if ((writer == null || !(writer instanceof DatanodeDescriptor)) && !newBlock) {
   
      writer = results.get(0).getDatanodeDescriptor();
    }

    // Keep a copy of original excludedNodes
    final Set<Node> oldExcludedNodes = new HashSet<Node>(excludedNodes);

    // choose storage types; use fallbacks for unavailable storages
    final List<StorageType> requiredStorageTypes = storagePolicy
        .chooseStorageTypes((short) totalReplicasExpected,
            DatanodeStorageInfo.toStorageTypes(results),
            unavailableStorages, newBlock);
    final EnumMap<StorageType, Integer> storageTypes =
        getRequiredStorageTypes(requiredStorageTypes);
    if (LOG.isTraceEnabled()) {
   
      LOG.trace("storageTypes=" + storageTypes);
    }

    try 
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值