当前位置: 移动技术网 > IT编程>数据库>其他数据库 > HBase BucketAllocatorException 异常剖析

HBase BucketAllocatorException 异常剖析

2020年04月23日  | 移动技术网IT编程  | 我要评论

近日,观察到hbase集群出现如下warn日志:

2020-04-18 16:17:03,081 warn [regionserver/xxx-bucketcachewriter-1] bucket.bucketcache:failed allocation for 604acc82edd349ca906939af14464bcb_175674734;
org.apache.hadoop.hbase.io.hfile.bucket.bucketallocatorexception: allocation too big size=1114202; adjust bucketcache sizes hbase.bucketcache.bucket.sizes to accomodate if size seems reasonable and you want it cached.

大概意思是说:由于block块太大(size=1114202)导致bucketallocator无法为其分配空间,如果想要被缓存并且觉得这样做合理,可以调整参数hbase.bucketcache.bucket.sizes。

默认情况下,hbase bucketcache 能够缓存block的最大值为512kb,即hbase.bucketcache.bucket.sizes=5120,9216,17408,33792,41984,50176,58368,66560,99328,132096,197632,263168,394240,525312,默认14种size标签。如果想要缓存更大的block块,我们可以调整参数为 hbase.bucketcache.bucket.sizes=5120,9216,17408,33792,41984,50176,58368,66560,99328,132096,197632,263168,394240,525312,1049600,2098176,此时最大容许2mb的block。

下面我们简单看一下对应源代码,涉及相关类为:
/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/bucket/bucketallocator.java
bucketallocator主要实现对bucket的组织管理,为block分配内存空间。

/**
   * allocate a block with specified size. return the offset
   * @param blocksize size of block
   * @throws bucketallocatorexception
   * @throws cachefullexception
   * @return the offset in the ioengine
   */
  public synchronized long allocateblock(int blocksize) throws cachefullexception,
      bucketallocatorexception {
    assert blocksize > 0;
    bucketsizeinfo bsi = rounduptobucketsizeinfo(blocksize);
    if (bsi == null) {
      throw new bucketallocatorexception("allocation too big size=" + blocksize +
        "; adjust bucketcache sizes " + blockcachefactory.bucket_cache_buckets_key +
        " to accomodate if size seems reasonable and you want it cached.");
    }
    long offset = bsi.allocateblock();

    // ask caller to free up space and try again!
    if (offset < 0)
      throw new cachefullexception(blocksize, bsi.sizeindex());
    usedsize += bucketsizes[bsi.sizeindex()];
    return offset;
  }

在调用rounduptobucketsizeinfo()方法后,返回结果如果为null则抛出bucketallocatorexception异常。看一下rounduptobucketsizeinfo()方法:

/**
 * round up the given block size to bucket size, and get the corresponding
 * bucketsizeinfo
*/
public bucketsizeinfo rounduptobucketsizeinfo(int blocksize) {
	for (int i = 0; i < bucketsizes.length; ++i)
	  if (blocksize <= bucketsizes[i])
		return bucketsizeinfos[i];
	return null;
}

该方法将传入的blocksize与数组bucketsizes从索引0开始取值进行比较,一旦小于bucketsize[i],则为该block分配bucketsizeinfos[i]大小的空间存放该block。

我们看一下数组bucketsizes的初始化过程:

private static final int default_bucket_sizes[] = { 4 * 1024 + 1024, 8 * 1024 + 1024,
  16 * 1024 + 1024, 32 * 1024 + 1024, 40 * 1024 + 1024, 48 * 1024 + 1024,
  56 * 1024 + 1024, 64 * 1024 + 1024, 96 * 1024 + 1024, 128 * 1024 + 1024,
  192 * 1024 + 1024, 256 * 1024 + 1024, 384 * 1024 + 1024,
  512 * 1024 + 1024 };

private final int[] bucketsizes;
bucketallocator(long availablespace, int[] bucketsizes)
  throws bucketallocatorexception {
  this.bucketsizes = bucketsizes == null ? default_bucket_sizes : bucketsizes;
  arrays.sort(this.bucketsizes);
  ...
}

可以看到,如果bucketsizes == null默认取数组default_bucket_sizes的值,并对该数组进行排序。这一步的排序为上一步的循环比较奠定了基础。

而数组default_bucket_sizes的值,也就是参数hbase.bucketcache.bucket.sizes的默认值。

扫描二维码关注博主公众号

转载请注明出处!欢迎关注本人微信公众号【hbase工作笔记】

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网