hbase发起批写入请求,很容易出现RegionServerTooBuzyException, 从源码分析解决

项目场景:

项目场景:使用hbase1.2.0发起批写入请求,很容易出现RegionServerTooBuzyException,

问题描述:

项目场景:使用hbase1.2.0发起批写入请求,很容易看到RegionTooBusyException, 出现这种问题:一般先百度一下,发现百度回来的方案,由于hbase有多个版本0.96,0.98,1.x,2.x,版本间的参数不一样。由于水平不足,百度回来的方案,基本不可用。 如何破解? 只能从源码种找答案
下图是hbase.1.2.0对应的hbase put数据流程

原因分析:

RegionTooBusyException是由put操作引起的,从hbase put流程源码入手,分析源码时,把客户端,服务端的交互,重要具体细节画出来
带着问题去源码找答案:
1.什么是RegionTooBusyException,是在哪抛出来的?
看源码思路:方法1:从请求路径开始client put 到server端
方法2:直接看异常抛出来的栈,分析栈的调用顺序,直接找到相应的类
2.什么时候flush,怎样触发的?
3.什么时候split? 触发条件?

这个图很大,需要直接看,不清晰,可以下载回来,进行拖动看

在这里插入图片描述
图1:hbase put流程图

17/12/07 11:49:41 INFO client.AsyncProcess: #70, table=www:person_dist, attempt=10/35 failed=826ops, last exception: org.apache.hadoop.hbase.RegionTooBusyException: org.apache.hadoop.hbase.RegionTooBusyException: Above memstore limit, regionName=www:person_dist,,1512617928531.a5bc9f2b05e93ca73beb7b1057d83e29., server=bigdata01.hzjs.co,16020,1510713472687, memstoreSize=216421096, blockingMemStoreSize=209715200
	at org.apache.hadoop.hbase.regionserver.HRegion.checkResources(HRegion.java:3647)
	at org.apache.hadoop.hbase.regionserver.HRegion.batchMutate(HRegion.java:2872)
	at org.apache.hadoop.hbase.regionserver.HRegion.batchMutate(HRegion.java:2823)
	at org.apache.hadoop.hbase.regionserver.RSRpcServices.doBatchOp(RSRpcServices.java:758)
	at org.apache.hadoop.hbase.regionserver.RSRpcServices.doNonAtomicRegionMutation(RSRpcServices.java:720)
	at org.apache.hadoop.hbase.regionserver.RSRpcServices.multi(RSRpcServices.java:2168)
	at org.apache.hadoop.hbase.protobuf.generated.ClientProtos$ClientService$2.callBlockingMethod(ClientProtos.java:33656)
	at org.apache.hadoop.hbase.ipc.RpcServer.call(RpcServer.java:2188)
	at org.apache.hadoop.hbase.ipc.CallRunner.run(CallRunner.java:112)
	at org.apache.hadoop.hbase.ipc.RpcExecutor.consumerLoop(RpcExecutor.java:133)
	at org.apache.hadoop.hbase.ipc.RpcExecutor$1.run(RpcExecutor.java:108)
	at java.lang.Thread.run(Thread.java:745)

栈分析:
RSRpcServices 接收到batchMutate事件,对HRegion进行写入,写入前进行资源检查HRegion.checkResources() 发出的异常,直接看这个方法

 private void checkResources() throws RegionTooBusyException {
    // If catalog region, do not impose resource constraints or block updates.
    if (this.getRegionInfo().isMetaRegion()) return;
   
    if (this.memstoreSize.get() > this.blockingMemStoreSize) {
      blockedRequestsCount.increment();
      requestFlush();
      throw new RegionTooBusyException("Above memstore limit, " +
          "regionName=" + (this.getRegionInfo() == null ? "unknown" :
          this.getRegionInfo().getRegionNameAsString()) +
          ", server=" + (this.getRegionServerServices() == null ? "unknown" :
          this.getRegionServerServices().getServerName()) +
          ", memstoreSize=" + memstoreSize.get() +
          ", blockingMemStoreSize=" + blockingMemStoreSize);
    }
  }

分析源码: 当this.memstoreSize.get() > this.blockingMemStoreSize) 就flush,发起RegionTooBusyException,this是当前region, 就是把 this.blockingMemStoreSize 调大就能解决问题,哪怎样调大它呢? 继续分析blockingMemStoreSize 是什么东西

  this.blockingMemStoreSize = this.memstoreFlushSize *
      conf.getLong(HConstants.HREGION_MEMSTORE_BLOCK_MULTIPLIER,
              HConstants.DEFAULT_HREGION_MEMSTORE_BLOCK_MULTIPLIER);
public static final String HREGION_MEMSTORE_BLOCK_MULTIPLIER =
        "hbase.hregion.memstore.block.multiplier";                
public static final int DEFAULT_HREGION_MEMSTORE_BLOCK_MULTIPLIER = 4;

HREGION_MEMSTORE_BLOCK_MULTIPLIER是   hbase.hregion.memstore.block.multiplier=4
追查:memstoreFlushSize 的大小是多少
    memstoreFlushSize = conf.getLong(HConstants.HREGION_MEMSTORE_FLUSH_SIZE,
      HTableDescriptor.DEFAULT_MEMSTORE_FLUSH_SIZE);
hbase.hregion.memstore.flush.size=1024*1024*128L128M

总结:blockingMemStoreSize 就是memstoreSize * block乘数 = 默认的128M*4
对应的参数是:hbase.hregion.memstore.flush.size 和 hbase.hregion.memstore.block.multiplier


解决方案:

<font

color=#999AAA >提示:这里填写该问题的具体解决方案:

调大hbase.hregion.memstore.flush.size 和 hbase.hregion.memstore.block.multiplier
增大这2个只,又需要增大jvm大小。

还需要结合put流程图中分析的上水位,低水位进行调整
getGlobalMemstoreSize() >= globalMemStoreLimitLowMark()
是否大于下水位 具体分析流程跟上面分析的memtore乘数一样,自己试试分析源码

put过程不要产生compact和split 如何控制,还是看图看源码

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值