這篇文章主要為大家展示了“hbase中如何使用split策略”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“hbase中如何使用split策略”這篇文章吧。
創(chuàng)新互聯(lián)公司專注于白山網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗。 熱誠為您提供白山營銷型網(wǎng)站建設(shè),白山網(wǎng)站制作、白山網(wǎng)頁設(shè)計、白山網(wǎng)站官網(wǎng)定制、重慶小程序開發(fā)服務(wù),打造白山網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供白山網(wǎng)站排名全網(wǎng)營銷落地服務(wù)。
在這個版本中使用的split策略是IncreasingToUpperBoundRegionSplitPolicy。確切來說他是0.94版本以后的策略。類為org/apache/hadoop/hbase/regionserver/IncreasingToUpperBoundRegionSplitPolicy.java
首先看一下 configureForRegion 方法,其中的initialSize 在以后會用到。這個方法其實(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),這個方法將initialSize 初始化為2*hbase.hregion.memstore.flush.size
再來看看其他的方法,有一個方法叫shouldSplit,顧名思義就是判斷能不能split。
@Override protected boolean shouldSplit() { if (region.shouldForceSplit()) return true; boolean foundABigStore = false; //得到同張表的在線region個數(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); //檢查每一個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); }
這是一個三目運(yùn)算,如果這個table中在線的region個數(shù)為0或則大于100,則使用getDesiredMaxFileSize()方法得到這個閥值,否則就使用getDesiredMaxFileSize()得到的閥值和initialSize * (tableRegionsCount的三次方)中小的那一個,在跟進(jìn)去getDesiredMaxFileSize方法看看
long getDesiredMaxFileSize() { return desiredMaxFileSize; }
這個方法是ConstantSizeRegionSplitPolicy中的方法,別覺得奇怪,因為IncreasingToUpperBoundRegionSplitPolicy extends ConstantSizeRegionSplitPolicy,這個找不到線索就看看這個類,然后找到了如下代碼
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做個抖動 float jitter = conf.getFloat("hbase.hregion.max.filesize.jitter", Float.NaN); if (!Float.isNaN(jitter)) { this.desiredMaxFileSize += (long)(desiredMaxFileSize * (RANDOM.nextFloat() - 0.5D) * jitter); } }
原來如果設(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,至于為什么抖動,有的人說是為了防止重啟regionServer時進(jìn)行大量的major compact,這種說法我暫時不明白,先放一放。
回到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(); } }
很簡單,就是看看有沒有引用文件,如果有則不能split,如果沒有則可以,再次回到shouldSplit方法,可以看到如果當(dāng)前的store的大小大于剛剛計算出的閥值,則返回true,算是通過split的判斷了。
好的,來總結(jié)一下:
hbase對一個region切分,有幾個條件:
1、如果是用戶請求切分,則不管什么情況都可以切分。
2、如果非用戶請求,并且這個region中任意store含有引用文件,則不切分
3、如果不是用戶請求,也沒有引用文件,則判斷每個store的大小,只要其中有一個大于閥值,則切分。這個閥值在上面已經(jīng)有說到。
說下這個策略的含義
0.94版本之前使用的是ConstantSizeRegionSplitPolicy策略,此策略只是大于一個基本固定的閥值就允許split,而現(xiàn)在的策略則是store大小大于一個變化的閥值就允許split,什么意思呢,舉個例子,當(dāng)hbase相關(guān)split的屬性都沒有配置,采用默認(rèn),一張表剛建立,默認(rèn)情況只有1個region,那么邏輯上是當(dāng)這個region的store大小超過 1*1*1*flushsize = 128M(沒有自己設(shè)置flushSize)時 才會允許split,如果達(dá)到這個值切分后,會有兩個region,其中一個region中的某個store大小大于 2*2*2*flushsize = 512M 時,則允許split,如此計算下去,直到這個大小超過了hbase.hregion.max.filesize+ hbase.hregion.max.filesize*隨機(jī)小數(shù)*hbase.hregion.max.filesize.jitter才允許split,基本也就固定了,如果粗劣的計算可以把這個hbase.hregion.max.filesize的大小作為最后的閥值,默認(rèn)是10G,也就說當(dāng)這個閥值變化到10G,這個閥值就基本上不再變化。
這種思想使得閥值達(dá)到一個基本固定的值之前先做了幾次split,而這幾次split的數(shù)據(jù)量很少,對hbase的影響也沒有那么大,而且相當(dāng)于數(shù)據(jù)導(dǎo)入量不大的時候就做了一次“預(yù)分region”,在一定意義上減少了以后的熱點(diǎn)region的發(fā)生。
以上是“hbase中如何使用split策略”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!