多region下的hbase写入问题

    原url地址为:http://koven2049.iteye.com/blog/1144526

    最近在集群上发现hbase写入性能受到较大下降,测试环境下没有该问题产生。而生产环境和测试环境的区别之一是生产环境的region数量远远多于测试环境,单台regionserver服务了约3500个region。
    通过jstack工具检查到大半写入线程BLOCKED状态在"public synchronized void reclaimMemStoreMemory() {"这一行,这是在put之前的一个检查过程。
    hbase在每次put以前,需要检查当前regionserver上的memstore是否超过总memstore阀值,如果超过,需要block住当前的写入,防止OOM,代码片段见下:

Java代码 复制代码  收藏代码
  1. /**  
  2.    * Check if the regionserver's memstore memory usage is greater than the  
  3.    * limit. If so, flush regions with the biggest memstores until we're down  
  4.    * to the lower limit. This method blocks callers until we're down to a safe  
  5.    * amount of memstore consumption.  
  6.    */  
  7.   public synchronized void reclaimMemStoreMemory() {   
  8.     if (isAboveHighWaterMark()) {   
  9.       lock.lock();   
  10.       try {   
  11.         while (isAboveHighWaterMark() && !server.isStopped()) {   
  12.           wakeupFlushThread();   
  13.           try {   
  14.             // we should be able to wait forever, but we've seen a bug where   
  15.             // we miss a notify, so put a 5 second bound on it at least.   
  16.             flushOccurred.await(5, TimeUnit.SECONDS);   
  17.           } catch (InterruptedException ie) {   
  18.             Thread.currentThread().interrupt();   
  19.           }   
  20.         }   
  21.       } finally {   
  22.         lock.unlock();   
  23.       }   
  24.     } else if (isAboveLowWaterMark()) {   
  25.       wakeupFlushThread();   
  26.     }   
  27.   }  
/**
   * Check if the regionserver's memstore memory usage is greater than the
   * limit. If so, flush regions with the biggest memstores until we're down
   * to the lower limit. This method blocks callers until we're down to a safe
   * amount of memstore consumption.
   */
  public synchronized void reclaimMemStoreMemory() {
    if (isAboveHighWaterMark()) {
      lock.lock();
      try {
        while (isAboveHighWaterMark() && !server.isStopped()) {
          wakeupFlushThread();
          try {
            // we should be able to wait forever, but we've seen a bug where
            // we miss a notify, so put a 5 second bound on it at least.
            flushOccurred.await(5, TimeUnit.SECONDS);
          } catch (InterruptedException ie) {
            Thread.currentThread().interrupt();
          }
        }
      } finally {
        lock.unlock();
      }
    } else if (isAboveLowWaterMark()) {
      wakeupFlushThread();
    }
  }

    这是一个同步操作,其中isAboveHighWaterMark()的代码如下:
Java代码 复制代码  收藏代码
  1. private boolean isAboveHighWaterMark() {   
  2.   return server.getGlobalMemStoreSize() >= globalMemStoreLimit;   
  3. }  
  private boolean isAboveHighWaterMark() {
    return server.getGlobalMemStoreSize() >= globalMemStoreLimit;
  }

    getGlobalMemStoreSize()里面的操作是遍历所有region,拿到每个region的memstore大小:
Java代码 复制代码  收藏代码
  1. public long getGlobalMemStoreSize() {   
  2.   long total = 0;   
  3.   for (HRegion region : onlineRegions.values()) {   
  4.     total += region.memstoreSize.get();   
  5.   }   
  6.   return total;   
  7. }  
 
 
Java代码 复制代码  收藏代码

  
  
  1. public long getGlobalMemStoreSize() {   
  2.   long total = 0;   
  3.   for (HRegion region : onlineRegions.values()) {   
  4.     total += region.memstoreSize.get();   
  5.   }   
  6.   return total;   

 

    如果region数量很多就比较杯具了,在单台服务器3500个region的环境下通过btrace跟踪到这一步需要耗时0.4ms,也就是每一个put会block所有线程0.4ms,这样无法发挥出server端并行处理能力,同时可以计算出无论如何配置,写tps无法超过1000/0.4=2500!
    产生这个问题的根本原因是在0.90.x版本中,region无法拿到regionserver的信息,因此只能通过实时计算来得到rs上总的memstore大小。在0.92.0或trunk版本中修改了HRegion的数据结构,让HRegion在初始化时得到regionserver的信息,因此可以实时记录memstore的总大小,并让每个region对象能拿到该值,于是这个isAboveHighWaterMark()就不再block住所有线程了,在region较多的场景下写性能得到较大提升。
    参照 https://issues.apache.org/jira/browse/HBASE-3694,可以以此patch为参考生成相应的0.90.x版本的patch
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值