HBase2.x精通:结合源码讲解Region的三种Spilt策略

微信公众号:大数据开发运维架构

关注可了解更多大数据相关的资讯。问题或建议,请公众号留言;

如果您觉得“大数据开发运维架构”对你有帮助,欢迎转发朋友圈

从微信公众号拷贝过来,格式有些错乱,建议直接去公众号阅读


一、概述

    

   最近在工作中接触到split,于是查看了这块的源代码,先看到了split的策略,今天就说说这个吧; 这里我是基于HDP版本的Hadoop集群,对应的HBase的版本为2.2.1,后续的分析都是基于该版本的源码做的分析, HBase-2.x支持7种Region自动拆分的策略,继承关系如下图所示:

 

二、针对这几种默认拆分策略做单独的说明。

1.RegionSplitPolicy

    RegionSplitPolicy是一个抽象类,其作为所有Region拆分策略的父类。在0.94版本以前,默认的拆分策略是ConstantSizeRegionSplitPolicy,在0.94版本以后,默认的策略为IncreasingToUpperBoundRegionSplitPolicy ,从2.0.0版本开始,默认的策略为SteppingSplitPolicy。

    在基类RegionSplitPolicy的源码中可以看到各个HBase版本默认的Spilt策略:


/**
 * A split policy determines when a Region should be split.
 *
 * @see SteppingSplitPolicy Default split policy since 2.0.0 
 * @see IncreasingToUpperBoundRegionSplitPolicy Default split policy since
 *      0.94.0
 * @see ConstantSizeRegionSplitPolicy Default split policy before 0.94.0
 */
@InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.CONFIG)
public abstract class RegionSplitPolicy extends Configured {
  ......................
}

2.ConstantSizeRegionSplitPolicy

    0.94版本前默认切分策略。这是最容易理解但也最容易产生误解的切分策略,从字面意思来看,当region大小大于某个阈值(由参数hbase.hregion.max.filesize控制)之后就会触发切分,实际上并不是这样,真正实现中这个阈值是对于某个store来说的,即一个region中最大store的大小大于设置阈值之后才会触发切分。另外一个大家比较关心的问题是这里所说的store大小是压缩后的文件总大小还是未压缩文件总大小,实际实现中store大小为压缩后的文件大小(采用压缩的场景)。

    ConstantSizeRegionSplitPolicy相对来来说最容易想到,但是在生产线上这种切分策略却有相当大的弊 端:切分策略对于大表和小表没有明显的区分。阈值(hbase.hregion.max.filesize)设置较大对大表比较友好,但是小表就有可能不会触发分裂,极端情况下可能就1个,这对业务来说并不是什么好事。如果设置较小则对小表友好,但一个大表就会在整个集群产生大量的region,这对于集群的管理、资源使用、failover来说都不是一件好事。

    源码中有一个方法叫shouldSplit,顾名思义就是判断能不能split,ConstantSizeRegionSplitPolicy类中对应的代码如下:

@Override
  protected boolean shouldSplit() {
    boolean force = region.shouldForceSplit();
    boolean foundABigStore = false;

    for (HStore store : region.getStores()) {
      // If any of the stores are unable to split (eg they contain reference files)
      // then don't split
      //看看有没有引用文件,如果有则不能split
      if ((!store.canSplit())) {
        return false;
      }
      // Mark if any store is big enough
      //这里就是判断是否大于一个固定值,这里默认就是10G,大于这个值就进行Split,不过hbase有个参数hbase.hregion.max.filesize.jitter
      //设置了一个抖动值,这里我没太理解明白,可暂时不考虑,直接认为达到一个固定值10G,
      //进行了region的分裂
      if (store.getSize() > desiredMaxFileSize) {
        foundABigStore = true;
      }
    }
    return foundABigStore || force;
  }

3.IncreasingToUpperBoundRegionSplitPolicy

    0.94版本~2.0版本默认切分策略。这种切分策略微微有些复杂,总体来看和ConstantSizeRegionSplitPolicy思路相同,一个region中最大store大小大于设置阈值就会触发切分。但是这个阈值并不像ConstantSizeRegionSplitPolicy是一个固定的值,而是会在一定条件下不断调整,调整规则和region所属表在当前regionserver上的region个数有关系 :(#regions) * (#regions) * (#regions) * flush size * 2,当然阈值并不会无限增大, 最大值为用户设置的MaxRegionFileSize。

    这种切分策略很好的弥补了ConstantSizeRegionSplitPolicy的短板,能够自适应大表和小表。而且在大集群条件下对于很多大表来说表现很优秀,但并不完美,这种策略下很多小表会在大集群中产生大量小region,分散在整个集群中。而且在发生region迁移时也可能会触发region分裂。

    IncreasingToUpperBoundRegionSplitPolicy类中是否分裂判断函数shouldSplit的代码如下:


@Override
  protected boolean shouldSplit() {
    boolean force = region.shouldForceSplit();
    boolean foundABigStore = false;
    // Get count of regions that have the same common table as this.region
    int tableRegionsCount = getCountOfCommonTableRegions();
    //这里就是是否分裂的关键判断逻辑
    long sizeToCheck = getSizeToCheck(tableRegionsCount);

    for (HStore store : region.getStores()) {
      // If any of the stores is unable to split (eg they contain reference files)
      // then don't split
      if (!store.canSplit()) {
        return false;
      }

      // Mark if any store is big enough
      long size = store.getSize();
      if (size > sizeToCheck) {
        LOG.debug("ShouldSplit because " + store.getColumnFamilyName() +
          " size=" + StringUtils.humanSize(size) +
          ", sizeToCheck=" + StringUtils.humanSize(sizeToCheck) +
          ", regionsWithCommonTable=" + tableRegionsCount);
        foundABigStore = true;
      }
    }

    return foundABigStore || force;
  }

这里关键判断逻辑在函数getSizeToCheck中,代码如下:


  /**
   * @return Region max size or {@code count of regions cubed * 2 * flushsize},
   * which ever is smaller; guard against there being zero regions on this server.
   */
  protected long getSizeToCheck(final int tableRegionsCount) {
    // safety check for 100 to avoid numerical overflow in extreme cases
    return tableRegionsCount == 0 || tableRegionsCount > 100
               ? getDesiredMaxFileSize()
               : Math.min(getDesiredMaxFileSize(),
                          initialSize * tableRegionsCount * tableRegionsCount * tableRegionsCount);
  }

    这是一个三目运算,如果这个table中在线的region个数为0或则大于100,则使用getDesiredMaxFileSize()方法得到这个阀值,否则就使用getDesiredMaxFileSize()得到的阀值和initialSize * (tableRegionsCount的三次方)中小的那一个。函数getDesiredMaxFileSize获取的可以理解成参数hbase.hregion.max.filesize配置的大小,默认是10G,为了更方便理解分裂的过程,这里举个例子:

    比如我们hbase.hregion.max.filesize默认配置的是10G,要想达到10G分裂的标准,前期需要经过以下4次拆分过程:

    第一次split:1^3 * 128*2= 256MB

    第二次split:2^3 * 128*2= 2048MB

    第三次split:3^3 * 128*2 = 6912MB

    第四次split:4^3 * 128*2 = 16384MB > 10GB,因此取较小的值10GB

    后面每次split的size都是10GB了。

 

4.SteppingSplitPolicy

    2.0版本以后默认切分策略。这种切分策略的切分阈值又发生了变化,相比IncreasingToUpperBoundRegionSplitPolicy简单了一些,依然和待分裂region所属表在当前regionserver上的region个 数有关系,如果只有1个Region的情况下,那第1次的拆分就是256M,后续则按配置的拆分文件大小(hbase.hregion.max.filesize默认值是10G)作为Region拆分标准。

    在IncreasingToUpperBoundRegionSplitPolicy策略中,针对大表的拆分表现很不错,但是针对小表会产生过多的Region,SteppingSplitPolicy则将小表的Region控制在一个合理的范围,对大表的拆分也不影响。

    SteppingSplitPolicy是IncreasingToUpperBoundRegionSplitPolicy的子类,其总共源码只有几行,如下:


/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.hadoop.hbase.regionserver;

import org.apache.yetus.audience.InterfaceAudience;

@InterfaceAudience.Private
public class SteppingSplitPolicy extends IncreasingToUpperBoundRegionSplitPolicy {
  /**
   * @return flushSize * 2 if there's exactly one region of the table in question
   * found on this regionserver. Otherwise max file size.
   * This allows a table to spread quickly across servers, while avoiding creating
   * too many regions.
   */
  @Override
  protected long getSizeToCheck(final int tableRegionsCount) {
    return tableRegionsCount == 1  ? this.initialSize : getDesiredMaxFileSize();
  }

}

三、Split策略设置

    Region拆分策略可以全局统一配置,也可以为单独的表指定拆分策略,下面整理了以下几种常用Split策略设置方法:

1.HBase的全局Spilt策略,可在hbase-site.xml添加如下属性:


<property>
  <name>hbase.regionserver.region.split.policy</name>
  <value>org.apache.hadoop.hbase.regionserver.IncreasingToUpperBoundRegionSplitPolicy</value>
</property>

2.使用JavaApi设置某个表的Split策略,代码如下:


HTableDescriptor tableDesc = new HTableDescriptor("table");
tableDesc.setValue(HTableDescriptor.SPLIT_POLICY, ConstantSizeRegionSplitPolicy.class.getName());
tableDesc.addFamily(new HColumnDescriptor(Bytes.toBytes("info")));
admin.createTable(tableDesc);

 

3.可在hbase shell控制台中设置某个表的Split策略(常用),命令如下:


hbase> create 'table1', {METADATA => {'SPLIT_POLICY' => 'org.apache.hadoop.hbase.regionserver.ConstantSizeRegionSplitPolicy'}},{NAME => 'info'}

4.用户也可在Configuration设置全局的Split策略,代码如下:


private static Configuration conf = HBaseConfiguration.create();
conf.set("hbase.regionserver.region.split.policy", "org.apache.hadoop.hbase.regionserver.SteppingSplitPolicy");

5.上面3中hbase shell控制台命令的设置,可以通过使用的HBaseConfiguration或按表进行全局设置,代码如下:

HTableDescriptor hTableDesc= ...;
hTableDesc.setValue(HTableDescriptor.SPLIT_POLICY, MyCustomSplitPolicy.class.getName());

    这里只介绍了HBase的三种默认的Split策略,其他的几种策略不太常用,有兴趣的可以去了解一下,这里不再讲解,感谢关注!!!

   如果觉得我的文章能帮到您,请关注微信公众号“大数据开发运维架构”,并转发朋友圈,谢谢支持!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

虾米球源码

您的鼓励将是我们创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值