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

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 bucket cache

    hbase bucket cache 作者的设计文档

    HbaseTemplate 操作hbase

    java 利用 sping-data-hadoop HbaseTemplate 操作hbase find get execute 等方法 可以直接运行

    pinpoint的hbase初始化脚本hbase-create.hbase

    搭建pinpoint需要的hbase初始化脚本hbase-create.hbase

    hbase的Rowkey设计方案.pdf

    HBase中设计有MemStore和BlockCache,分别对应列族/Store级别的写⼊缓存,和RegionServer级别的读取缓存。如果RowKey过 长,缓存中存储数据的密度就会降低,影响数据落地或查询效率。 1.2 hbase的设计原则以及解决...

    HBase数据库设计.doc

    1. HBase有哪些基本的特征? 1 HBase特征: 1 2. HBase相对于关系数据库能解决的问题是什么? 2 HBase与关系数据的区别? 2 HBase与RDBMS的区别? 2 3. HBase的数据模式是怎么样的?即有哪些元素?如何存储?等 3 1...

    HBase(hbase-2.4.9-bin.tar.gz)

    HBase(hbase-2.4.9-bin.tar.gz)是一个分布式的、面向列的开源数据库,该技术来源于 Fay Chang 所撰写的Google论文“Bigtable:一个结构化数据的分布式存储系统”。就像Bigtable利用了Google文件系统(File System...

    Hbase底层剖析结构

    Hbase底层剖析结构,Hbase底层剖析结构,Hbase底层剖析结构

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

    hbase 常用参数含义,默认值,调优建议(必须参数,split,compaction,blockcache,memstore flush,hlog,zookeeper,其他,等相参数名称、含义、默认值、调优建议)

    HBase学习利器:HBase实战

    HBase开发实战,HBase学习利器:HBase实战

    Hbase资源整理集合

    HBase 官方文档.pdf HBase的操作和编程.pdf HBase Cpressr优化与实验 郭磊涛.pdf null【HBase】Data Migratin frm Gri t Clu Cmputing - Natural Sienes .pdf 分布式数据库HBase快照的设计与实现.pdf 【HBase】...

    hbase-sdk是基于hbase-client和hbase-thrift的原生API封装的一款轻量级的HBase ORM框架

    hbase-sdk是基于hbase-client和hbase-thrift的原生API封装的一款轻量级的HBase ORM框架。 针对HBase各版本API(1.x~2.x)间的差异,在其上剥离出了一层统一的抽象。并提供了以类SQL的方式来读写HBase表中的数据。对...

    HBase开启审计日志

    HBase开启审计日志

    java大数据作业_3HBase

    1. 请用java集合的代码描述HBase的表结构 2. 请简述HBase中数据写入最后导致Region分裂的全过程 3. 如果设计一个笔记的表,表中要求有笔记的属性和笔记的内容,怎么做 4. HBase部署时如何指定多个zookeeper 5. HBase...

    hbase资料api

    HBASE

    HBase3.0参考指南

    HBase3.0参考指南 This is the official reference guide for the HBase version it ships with. Herein you will find either the definitive documentation on an HBase topic as of its standing when the ...

    hbase 资源合集 hbase 企业应用开发实战 权威指南 hbase 实战 hbase 应用架构

    hbase 资源合集 hbase 企业应用开发实战 权威指南 hbase 实战 hbase 应用架构

    Hbase基本用法简介

    Hbase shell 、Hbase api、Hbase 配置

    实验三:熟悉常用的HBase操作

    A.3实验三:熟悉常用的HBase操作 本实验对应第5章的内容。 A.3.1 实验目的 (1)理解HBase在Hadoop体系结构中的角色。(2)熟练使用HBase操作常用的 Shell命令。(3)熟悉HBase操作常用的 Java API。 A.3.2 实验平台 (1...

    Hbase2.2.4.rar

    Hbase2.2.4安装包,HBase是一个分布式的、面向列的开源数据库,该技术来源于 Fay Chang 所撰写的Google论文“Bigtable:一个结构化数据的分布式存储系统”。就像Bigtable利用了Google文件系统(File System)所提供...

    Hbase与zookeeper文档

    HBase即Hadoop Database,是一个高可靠性、高性能、面向列、可伸缩的分布式存储系统,利用HBase技术可在普通的PC Server上搭建起大规模结构化存储集群。 HBase是Google Bigtable的开源实现,类似Google Bigtable利用...

Global site tag (gtag.js) - Google Analytics