Hbase compact以及split跟踪

 

2017年06月30日 10:13:48 tom_fans 阅读数:847

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/tom_fans/article/details/73937375

为了准确了解HBASE内部工作原理,我们需要做一些测试,在大量数据插入的情况下,HBASE内部到底有什么表现?  比如插入速度,  hstore compact,split等相关活动,了解了这些才能更好的维护HBASE系统本身。

此次测试会有几轮,所以测试到哪里就写到哪里,我随便找了一张大概120W来的表,我会写一个mapreduce任务,来读取这张表,再写入另外一个测试表: test2, 没有选择更大的表是因为毕竟整个拷贝是需要时间,通常20分钟-30分钟,太大的表,不太利于跟踪。 拷贝过程,HBASE会针对此表有相关的活动日志,依据日志,我们来看看HBASE到底在干什么。

测试开始, 下面是我的mapreduce任务进度,reduce开始的时间,实际就是写入HBASE的时间,那么从11:36开始,应该HBASE在插入

17/06/29 11:31:41 INFO mapreduce.Job:  map 71% reduce 0%
17/06/29 11:32:07 INFO mapreduce.Job:  map 81% reduce 0%
17/06/29 11:32:08 INFO mapreduce.Job:  map 86% reduce 0%
17/06/29 11:32:19 INFO mapreduce.Job:  map 86% reduce 29%
17/06/29 11:36:07 INFO mapreduce.Job:  map 95% reduce 29%
17/06/29 11:36:11 INFO mapreduce.Job:  map 96% reduce 29%

跟踪日志过程

1.  11:36分日志显示flush一个memstore,大小为129M, 这个和设置的参数值是一样的,hbase.hstore.compactionThreshold=3  ,此时发生的是minor合并

2017-06-29 11:36:48,023 INFO org.apache.hadoop.hbase.regionserver.DefaultStoreFlusher: Flushed, sequenceid=160, memsize=128.7 M, hasBloomFilter=true, into tmp file hdfs://nameservice1/hbase/data/default/test2/786ef51a9c89f0e31073ba8aafc7ef94/.tmp/1fa335caa3144c8da5e0ca7697f551cf
2017-06-29 11:36:48,041 INFO org.apache.hadoop.hbase.regionserver.HStore: Added hdfs://nameservice1/hbase/data/default/test2/786ef51a9c89f0e31073ba8aafc7ef94/cf/1fa335caa3144c8da5e0ca7697f551cf, entries=636412, sequenceid=160, filesize=49.9 M
2017-06-29 11:36:48,054 INFO org.apache.hadoop.hbase.regionserver.HRegion: Finished memstore flush of ~128.74 MB/134994216, currentsize=31.53 MB/33059808 for region test2,,1498706810880.786ef51a9c89f0e31073ba8aafc7ef94. in 1343ms, sequenceid=160, compaction requested=true

跟踪HFILE合并, 日志显示,3个文件合并在一起,一共148M,花费的时间为3秒,很显然minor合并的速度还是很快的。

2017-06-29 11:36:48,058 INFO org.apache.hadoop.hbase.regionserver.HStore: Starting compaction of 3 file(s) in cf of test2,,1498706810880.786ef51a9c89f0e31073ba8aafc7ef94. into tmpdir=hdfs://nameservice1/hbase/data/default/test2/786ef51a9c89f0e31073ba8aafc7ef94/.tmp, totalSize=148.3 M

2017-06-29 11:36:51,792 INFO org.apache.hadoop.hbase.regionserver.CompactSplitThread: Completed compaction: Request = regionName=test2,,1498706810880.786ef51a9c89f0e31073ba8aafc7ef94., storeName=cf, fileCount=3, fileSize=148.3 M, priority=7, time=17006286308699473; duration=3sec

4. flush  

5. flush 

6. 要求合并(此时第一个合并之后只有一个文件,加上flush的2个文件,一共3个,达到了合并条件)

7. 要求split (split之后为2个文件)

8. flush

9. 要求合并(之前split为2个文件,加上flush的一个为3个文件,达到合并条件)

10. 要求split

以上是根据日志显示得到的一个跟踪过程。 我们可以看到minor compact速度很快,根据参数设置,每3个文件就会合并一次。 至于major compact由hbase.hregion.majorcompaction来控制,
默认是7天时间,0表示关闭major compact.  所以从理论来讲,minor compact对于一个数据量大的系统,可能时时刻刻在合并, 因为memstore 默认128M可能1分钟就满了,刷出之后产生HFILE,然后达到合并条件就合并。

而split有3个策略,默认是KeyPrefixRegionSplitPolicy, ConstantSizeRegionSplitPolicy能完全禁止自动拆分,设置这个策略之后,然后修改region的max filesize,比如100G,那么基本就可以关闭自动拆分。


根据以上合并以及拆分理论知识,我们假设有一个系统负载极大,不停的大量数据写入,那么我们可以知道,HBASE内部在不停的合并,达到拆分规则又拆分,又合并,又拆分,周而复始。
在拆分的时候,1个大region拆分成2个小region, 然后修改meta,再online2个小region,  删除大的region. 但是在这过程,我们知道数据还在不停的写入,hbase.hstore.blockingWaitTime 默认90秒,超过这个时间又会放行插入和更新。很显然,出现这种情况之后,小region如果出现了需要split的情况怎么办? 开始的合并还没有结束,大region还没有offline, 小region又要拆分。 

如果出现了上面的情况,我不知道具体HBASE是什么规则,但是我想这是一个极度复杂的处理,简单处理的话只有BLOCK插入和更新,等待合并或者拆分结束。目前我还没找到有完全BLOCK HBASE插入和更新的参数, 所以为了更好管理HBASE, 建议关闭自动拆分,为什么? 不仅仅是为了说SPLIT可能会影响性能,如果说SPLIT会影响,那么合并也会影响,更多的是,拆分和合并我们要有取舍,关闭了自动拆分,人为来控制,那么在HBASE内部仅仅存在合并,至少不会出现上述极度复杂的情况。

最后,如果系统负载极大的时候,rowkey分配不规则,大量线程往一个region写数据,默认单个memstore是128M,最大大小为128*2=256M, 这个时候按照规则会BLOCK写入,甚至出现org.apache.hadoop.hbase.RegionTooBusyException: org.apache.hadoop.hbase.RegionTooBusyException: Above memstore limit  memstoreSize=269744800, blockingMemStoreSize=268435456 之类的错误。  

这里简单说一下memstore block写入规则,默认memstore size=128M,  结合<span white-space:normal;background-color:#f5f5f5;"="" style="word-wrap: break-word; color: rgb(85, 85, 85); font-family: 宋体, Arial;">hbase.hregion.memstore.block.multiplier=2 ,也就是说memstore最大大小为256M, 将BLOCK写入,阻止大量写入避免出现outofmemory错误. 上面你看到的above memstore size > 256M.

所以预先分区以及估算写入量就显的非常重要,如果你的系统负载并没有那么大,那么就显的不是那么重要了。

猜你喜欢

转载自blog.csdn.net/wangshuminjava/article/details/85006344