`
punishzhou
  • 浏览: 142689 次
社区版块
存档分类
最新评论

HBase的Block cache

 
阅读更多

HBase上Regionserver的内存分为两个部分,一部分作为Memstore,主要用来写;另外一部分做BlockCache,用来读,当然Memstore也有读的功效,不过由于Hbase的scan机制,从Memsotre读到数据的效果一般。

 

今天主要来分析下Hbase的BlockCache机制,并且阐述其中碰到的一个RTE异常。

 

话不多说,首先来看看Hbase的存储机制。

其实际存储文件是HFile格式的,这是一个HDFS上的Seq的二进制流

HFILE由以下几部分组成

DATABLOCK    DATABLOCK 。。。标志 METABLOCK   METABLOCK  。。。DATAINDEX  METAINDEX  TRAILER

TRAILER为头指针,指向DATAINDEX和METAINDEX,DATAINDEX和METAINDEX分别指向BLOCK的起始位置

DATABLOCK的结构是keyvalue键值对,具体的结构就不分析了

 

LRU顾名思义就是最近最久未使用方法,查找到内存中最近最久未使用的进行淘汰

RS在启动的时候会启动一个线程专门进行LRU淘汰如下所示:

 

public void run() {
      while(true) {
        synchronized(this) {
          try {
            this.wait();
          } catch(InterruptedException e) {}
        }
        LruBlockCache cache = this.cache.get();
        if(cache == null) break;
        cache.evict();
      }
    }

 该段代码是一个循环等待LRU进程唤醒条件的发生,当该条件满足时会调用cache的evict()方法进行淘汰。

 

那么产生的条件是什么呢

整个RS的LRU维护一个HashMap<string,Block>,String 是一个blockpath,由storefilepath+标记+blocknum组成
当有读请求发生时首先会对当前storefile的read对象,synchronized (metaIndex.blockKeys[block])
然后get,若无则加进map中。有则直接返回Block

 

当加入map以后map的size达到一个阈值,此时:

  public void evict() {
      synchronized(this) {
        this.notify(); // FindBugs NN_NAKED_NOTIFY
      }
    }

 该函数会通知LRU线程进行淘汰。淘汰的规则如下:

 

将MAP中的数据装入3个桶:In-Memory,muti,single 。3个桶都有容量,且各自维护一个list用来存放放入其中的Block

删除的是批量删除的形式,即如果Map的size大于阈值A,那么此时会释放到一个MAP的初始值大小。

 

首先选择将要删除的桶,超过桶容量最大的优先选择删除算法如下所示

 

 while((bucket = bucketQueue.poll()) != null) {
        long overflow = bucket.overflow();
        if(overflow > 0) {
          long bucketBytesToFree = Math.min(overflow,
            (bytesToFree - bytesFreed) / remainingBuckets);
          bytesFreed += bucket.free(bucketBytesToFree);
        }
        remainingBuckets--;
      }

 

cache可以高效地提升hbase的读TPS,在hbase中具有重要的作用。

Memstore则是写操作的关键,二者在hbase都有重要的作用,当然是越大越好。不过hbase规定二者之和不得超过可用内存的0.8呗,否则会产生不可预知的错误。

 

 

下面来看看碰到的一个RTE异常

synchronized (metaIndex.blockKeys[block]) {
        metaLoads++;
        // Check cache for block.  If found return.
        if (cache != null) {
          ByteBuffer cachedBuf = cache.getBlock(name + "meta" + block,
              cacheBlock);
          if (cachedBuf != null) {
            // Return a distinct 'shallow copy' of the block,
            // so pos doesnt get messed by the scanner
            cacheHits++;
            return cachedBuf.duplicate();
          }
          // Cache Miss, please load.
        }

        ByteBuffer buf = decompress(metaIndex.blockOffsets[block],
          longToInt(blockSize), metaIndex.blockDataSizes[block], true);
        byte [] magic = new byte[METABLOCKMAGIC.length];
        buf.get(magic, 0, magic.length);

        if (! Arrays.equals(magic, METABLOCKMAGIC)) {
          throw new IOException("Meta magic is bad in block " + block);
        }

        // Create a new ByteBuffer 'shallow copy' to hide the magic header
        buf = buf.slice();

        readTime += System.currentTimeMillis() - now;
        readOps++;
        readData +=longToInt(blockSize);

        // Cache the block
        if(cacheBlock && cache != null) {
          cache.cacheBlock(name + "meta" + block, buf.duplicate(), inMemory);
        }

        return buf;
      }

 

这段代码逻辑性本身是没有问题,但是当出现以下情况时就有触发异常

LRU维护一个HashMap<string,Block>,String 是一个blockpath,由storefilepath+标记+blocknum组成。

当有读请求发生时首先会对当前storefile的read对象,synchronized (metaIndex.blockKeys[block])

然后get,若无则加进map中。有则直接返回Block

 

但是这个逻辑在Region split和compact的时候会有问题。

 

假设A split B 和C,此时读取C,那么首先会去get,发现不存在,然后将C的blockpath putin map。

 

如果compact刚好在get和put之间结束,此时又有读请求过来,那么此时它们的storefilepath是一样的;

由于是getMetaBlock,因此它们的blocknum也一致,故blockpath也一致;

 

而且compact结束以后创建的是新的reader对象,与C原来的HalfStoreFileReader对象不一致。此时该读请求也会去get map,发现map中没有该blockpath,也会执行put操作。

 

这样对同一block会有两次put,会抛出RTE: Cached an already cached block 目前来看这个异常不会造成数据丢失,对读操作也无影响,主要发生在getMetaBlock的时候。

 

由于compact以后对于数据所在block的number进行了更新故在LoadBlock时几乎不发生

 

目前来看这个异常不会造成数据丢失,对读操作也无影响,主要发生在getMetaBlock的时候。
由于compact以后对于数据所在block的number进行了更新故在LoadBlock时几乎不发生

 

 

 

分享到:
评论

相关推荐

    HBase堆外内存测试

    HBase的BlockCache是一种用于提高读取性能的重要机制,它主要用于缓存HFile的Block数据,以减少磁盘I/O操作,从而加快读取速度。BlockCache分为两种类型:LruCache和BucketCache。 - **LruCache**:基于最近最少...

    hbase bucket cache

    ### HBase Bucket Cache:一种高效的缓存管理方案 #### 概述 HBase Bucket Cache 是一个针对 HBase 的块缓存实现,旨在解决 CMS(Concurrent Mark Sweep)垃圾收集器和堆内存碎片带来的性能问题,并提供更大的缓存...

    HBase的性能优化

    HBase的Block Cache是 RegionServer 中的一块缓存区域,用于存储频繁访问的数据块。增大Block Cache的大小可以提高读取性能。默认情况下,HBase的Block Cache大小为0.0,可以根据实际情况调整这个值。例如,将Block ...

    Hbase运维手册范本.doc

    BlockCache 是 HBase 中的一种缓存机制,用于存储经常访问的数据。通过调整 BlockCache 的大小,可以提高 HBase 的读取性能。 3. 读写请求数 读写请求数是一个重要的性能指标,通过观察读写请求数,可以了解每台 ...

    《大数据平台搭建与配置管理》期中试题试卷及答案.docx

    - **详细解析**:虽然BlockCache能够显著提高HBase的读取性能,但并不是所有类型的数据块缓存都能够提高效率。例如,如果数据块访问频率很低,将其放入BlockCache中可能并不会带来明显的性能提升。 19. **HBase ...

    hbase的hbase-1.2.0-cdh5.14.2.tar.gz资源包

    5. **BlockCache**:配置BlockCache大小,缓存最近访问的数据,提高读取速度。 ### 总结 HBase是大数据处理领域的重要工具,尤其适合实时查询和大规模数据存储。理解并掌握HBase的核心概念、安装配置、数据模型...

    HBase源代码 hbase-0.98.23

    例如,`org.apache.hadoop.hbase.regionserver.HStore`类实现了MemStore和BlockCache,它们分别缓存内存中的新写入数据和硬盘上的热数据,提高读写效率。同时,HBase还支持Compaction操作,通过`org.apache.hadoop....

    hbase 数据库

    11. **优化策略**:包括合理设置Region大小、预分区表、选择合适的Column Family、启用BlockCache等,以提升HBase的性能。 12. **安全配置**:在生产环境中,可能需要配置HBase与Kerberos进行集成,以实现身份验证...

    Hbase运维手册.pdf

    此外,HBase的内存管理还包括了BlockCache与Memstore的大小比例配置,一般默认BlockCache为20%,Memstore为40%。在读密集型应用中,可以增大BlockCache,减小Memstore,以优化读取性能。BlockCache的三个优先级队列...

    HBase配置

    `hbase.blockcache.size`配置全局BlockCache的大小,它用于缓存数据块以提高读取性能。`hbase.hregion.memstore.block.multiplier`控制内存中memstore的大小,防止过多数据堆积导致RegionServer崩溃。 10. **性能...

    HBase 2.0 MOB 保存图片小视频利器-upload_HBase2.0MOB_

    create 'ImagesTable', 'Images', {NAME =&gt; 'ImageData', VERSIONS =&gt; 1, BLOCKCACHE =&gt; true, COMPRESSION =&gt; 'NONE', MOB_ENABLED =&gt; true, MOB_THRESHOLD =&gt; 1048576} ``` 3. 上传文件:使用HBase的Java API...

    hbase资料_hbase-default.xml.zip

    5. **文件系统和缓存设置**:`fs.defaultFS`设定默认的HDFS文件系统,`hbase.hregion.blockmultiplier`控制BlockCache的大小,`hbase.hregion.memstore.block.multiplier`则用于控制MemStore的大小。 6. **客户端...

    HBase最佳实践-读性能优化策略-3——HBase服务器端优化.pdf

    - 观察与确认:分析缓存未命中率和配置,同时关注GC日志,评估BlockCache配置的有效性。 - 优化建议:若内存小于20GB,选择LRUBlockCache;否则,考虑使用BucketCache的offheap模式,以减少GC影响。HBase 2.0的...

    hbase-1.6.0-bin.tar.gz

    例如,它改进了BlockCache的管理,提高了缓存效率;增强了MemStore的压缩算法,降低了存储成本;同时,还优化了Region分裂过程,减少了对系统的影响。 2. **多版本支持**:HBase允许用户保留多个版本的数据,便于...

    hbase的Rowkey设计方案.pdf

    在HBase中,MemStore和BlockCache是两个关键的缓存机制。MemStore用于列族/Store级别的写入缓存,而BlockCache则服务于RegionServer级别的读取缓存。Rowkey长度的控制尤为重要,过长的Rowkey会导致缓存中数据密度...

    HBase配置项说明及调优建议.zip

    6. **缓存和预读配置**:`hbase.hregion.blockcache.size`设置了BlockCache的大小,提高读取性能。`hbase.client.scanner.caching`控制每次从RegionServer获取的行数,合理设置可以减少网络传输。 7. **负载均衡**...

    hbase API

    - BlockCache: 缓存热数据,加速读取速度。 - Region Splitting & Balancing: 自动分裂大Region和负载均衡,保持集群健康运行。 6. **HBase MPI** - MPI(Message Passing Interface)通常用于高性能计算,将...

    大数据书籍-Hbase架构设计(高清)

    5. **性能优化**:分享在项目实践中遇到的问题及解决方案,如Region大小调整、Compaction策略、BlockCache的使用等,以提高Hbase的读写性能。 6. **案例分析**:通过实际项目案例,展示Hbase在互联网、物联网、日志...

    hbase1.0.3_part1

    3. **实时查询**:HBase支持实时读写操作,通过内存缓存和BlockCache机制,提供了亚秒级的查询响应速度。 4. **稀疏性**:HBase可以存储大量的稀疏数据,即许多行或列可能存在大量缺失值,只存储有实际数据的位置,...

Global site tag (gtag.js) - Google Analytics