溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

hbase中如何使用split策略

發(fā)布時(shí)間:2021-12-08 16:06:46 來(lái)源:億速云 閱讀:384 作者:小新 欄目:云計(jì)算

這篇文章主要為大家展示了“hbase中如何使用split策略”,內(nèi)容簡(jiǎn)而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“hbase中如何使用split策略”這篇文章吧。

    在這個(gè)版本中使用的split策略是IncreasingToUpperBoundRegionSplitPolicy。確切來(lái)說(shuō)他是0.94版本以后的策略。類為org/apache/hadoop/hbase/regionserver/IncreasingToUpperBoundRegionSplitPolicy.java 
    首先看一下 configureForRegion 方法,其中的initialSize 在以后會(huì)用到。這個(gè)方法其實(shí)主要目的也就是在初始化initialSize 

@Override
  protected void configureForRegion(HRegion region) {
    super.configureForRegion(region);
    Configuration conf = getConf();
    //如果設(shè)置了hbase.increasing.policy.initial.size,則使用用戶設(shè)置的
    this.initialSize = conf.getLong("hbase.increasing.policy.initial.size", -1);
    if (this.initialSize > 0) {
      return;
    }
    //如果沒有設(shè)置,看hbase.hregion.memstore.flush.size有沒有
    //如果設(shè)置了則initialSize=2*hbase.hregion.memstore.flush.size,
    //如果沒有則使用默認(rèn)的1024*1024*128L  (128M)
    HTableDescriptor desc = region.getTableDesc();
    if (desc != null) {
      this.initialSize = 2*desc.getMemStoreFlushSize();
    }
    if (this.initialSize <= 0) {
      this.initialSize = 2*conf.getLong(HConstants.HREGION_MEMSTORE_FLUSH_SIZE,
        HTableDescriptor.DEFAULT_MEMSTORE_FLUSH_SIZE);
    }
  }

如果配置默認(rèn),這個(gè)方法將initialSize 初始化為2*hbase.hregion.memstore.flush.size
再來(lái)看看其他的方法,有一個(gè)方法叫shouldSplit,顧名思義就是判斷能不能split。

@Override
  protected boolean shouldSplit() {
    if (region.shouldForceSplit()) return true;
    boolean foundABigStore = false;
    //得到同張表的在線region個(gè)數(shù)
    // Get count of regions that have the same common table as this.region
    int tableRegionsCount = getCountOfCommonTableRegions();
    //得到分割的閥值
    // Get size to check
    long sizeToCheck = getSizeToCheck(tableRegionsCount);
    //檢查每一個(gè)store,如果有不能split的則此次判斷為false
    for (Store store : region.getStores().values()) {
      // If any of the stores is unable to split (eg they contain reference files)
      // then don't split
    	//如果當(dāng)前region不能分割,則返回false
      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=" + size + ", sizeToCheck=" + sizeToCheck +
          ", regionsWithCommonTable=" + tableRegionsCount);
        foundABigStore = true;
      }
    }

    return foundABigStore;
  }

其中l(wèi)ong sizeToCheck = getSizeToCheck(tableRegionsCount);這句很重要,跟進(jìn)去查看

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(),
        this.initialSize * tableRegionsCount * tableRegionsCount * tableRegionsCount);
  }

這是一個(gè)三目運(yùn)算,如果這個(gè)table中在線的region個(gè)數(shù)為0或則大于100,則使用getDesiredMaxFileSize()方法得到這個(gè)閥值,否則就使用getDesiredMaxFileSize()得到的閥值和initialSize * (tableRegionsCount的三次方)中小的那一個(gè),在跟進(jìn)去getDesiredMaxFileSize方法看看
 

long getDesiredMaxFileSize() {
    return desiredMaxFileSize;
  }

這個(gè)方法是ConstantSizeRegionSplitPolicy中的方法,別覺得奇怪,因?yàn)镮ncreasingToUpperBoundRegionSplitPolicy extends ConstantSizeRegionSplitPolicy,這個(gè)找不到線索就看看這個(gè)類,然后找到了如下代碼

private long desiredMaxFileSize;

  @Override
  protected void configureForRegion(HRegion region) {
    super.configureForRegion(region);
    Configuration conf = getConf();
    HTableDescriptor desc = region.getTableDesc();
    if (desc != null) {
      this.desiredMaxFileSize = desc.getMaxFileSize();
    }
    //設(shè)置desiredMaxFileSize = hbase.hregion.max.filesize的大小默認(rèn)是10G
    if (this.desiredMaxFileSize <= 0) {
      this.desiredMaxFileSize = conf.getLong(HConstants.HREGION_MAX_FILESIZE,
        HConstants.DEFAULT_MAX_FILE_SIZE);
    }
    //如果設(shè)置了hbase.hregion.max.filesize.jitter  則desiredMaxFileSize做個(gè)抖動(dòng)
    float jitter = conf.getFloat("hbase.hregion.max.filesize.jitter", Float.NaN);
    if (!Float.isNaN(jitter)) {
      this.desiredMaxFileSize += (long)(desiredMaxFileSize * (RANDOM.nextFloat() - 0.5D) * jitter);
    }
  }

原來(lái)如果設(shè)置了hbase.hregion.max.filesize.jitter,則用HREGION_MAX_FILESIZE + HREGION_MAX_FILESIZE*隨機(jī)小數(shù)*hbase.hregion.max.filesize.jitter,其中jitter默認(rèn)為0.5,HREGION_MAX_FILESIZE 其實(shí)就是hbase.hregion.max.filesize,默認(rèn)是10G,至于為什么抖動(dòng),有的人說(shuō)是為了防止重啟regionServer時(shí)進(jìn)行大量的major compact,這種說(shuō)法我暫時(shí)不明白,先放一放。

回到shouldSplit方法中,我們看看canSplit方法做了什么?
 

@Override
  public boolean canSplit() {
    this.lock.readLock().lock();
    try {
      // Not split-able if we find a reference store file present in the store.
      boolean result = !hasReferences();
      if (!result && LOG.isDebugEnabled()) {
        LOG.debug("Cannot split region due to reference files being there");
      }
      return result;
    } finally {
      this.lock.readLock().unlock();
    }
  }



很簡(jiǎn)單,就是看看有沒有引用文件,如果有則不能split,如果沒有則可以,再次回到shouldSplit方法,可以看到如果當(dāng)前的store的大小大于剛剛計(jì)算出的閥值,則返回true,算是通過(guò)split的判斷了。

好的,來(lái)總結(jié)一下:

hbase對(duì)一個(gè)region切分,有幾個(gè)條件:
1、如果是用戶請(qǐng)求切分,則不管什么情況都可以切分。
2、如果非用戶請(qǐng)求,并且這個(gè)region中任意store含有引用文件,則不切分
3、如果不是用戶請(qǐng)求,也沒有引用文件,則判斷每個(gè)store的大小,只要其中有一個(gè)大于閥值,則切分。這個(gè)閥值在上面已經(jīng)有說(shuō)到。

說(shuō)下這個(gè)策略的含義
0.94版本之前使用的是ConstantSizeRegionSplitPolicy策略,此策略只是大于一個(gè)基本固定的閥值就允許split,而現(xiàn)在的策略則是store大小大于一個(gè)變化的閥值就允許split,什么意思呢,舉個(gè)例子,當(dāng)hbase相關(guān)split的屬性都沒有配置,采用默認(rèn),一張表剛建立,默認(rèn)情況只有1個(gè)region,那么邏輯上是當(dāng)這個(gè)region的store大小超過(guò) 1*1*1*flushsize = 128M(沒有自己設(shè)置flushSize)時(shí) 才會(huì)允許split,如果達(dá)到這個(gè)值切分后,會(huì)有兩個(gè)region,其中一個(gè)region中的某個(gè)store大小大于 2*2*2*flushsize = 512M 時(shí),則允許split,如此計(jì)算下去,直到這個(gè)大小超過(guò)了hbase.hregion.max.filesize+ hbase.hregion.max.filesize*隨機(jī)小數(shù)*hbase.hregion.max.filesize.jitter才允許split,基本也就固定了,如果粗劣的計(jì)算可以把這個(gè)hbase.hregion.max.filesize的大小作為最后的閥值,默認(rèn)是10G,也就說(shuō)當(dāng)這個(gè)閥值變化到10G,這個(gè)閥值就基本上不再變化。
 

這種思想使得閥值達(dá)到一個(gè)基本固定的值之前先做了幾次split,而這幾次split的數(shù)據(jù)量很少,對(duì)hbase的影響也沒有那么大,而且相當(dāng)于數(shù)據(jù)導(dǎo)入量不大的時(shí)候就做了一次“預(yù)分region”,在一定意義上減少了以后的熱點(diǎn)region的發(fā)生。

以上是“hbase中如何使用split策略”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI