`
yangbutao
  • 浏览: 1036 次
  • 性别: Icon_minigender_1
  • 来自: 上海
最近访客 更多访客>>
社区版块
存档分类
最新评论

关于HBase MVCC的设计原理以及MVCC所引起的一个scan问题

阅读更多
最近在使用HBase0.94版本的时,偶尔会出现,HRegionInfo was null or empty in Meta 的警告

java.io.IOException: HRegionInfo was null or empty in Meta for writetest, row=lot_let,9399239430349923234234,99999999999999
at org.apache.hadoop.hbase.client.MetaScanner.metaScan(MetaScanner.java:170)




在客户端的MetaScanner.metaScan实现中

metaTable = new HTable(configuration, HConstants.META_TABLE_NAME);

Result startRowResult = metaTable.getRowOrBefore(searchRow,HConstants.CATALOG_FAMILY);

if (startRowResult == null) { throw new TableNotFoundException("Cannot find row in .META. for table: " + Bytes.toString(tableName) + ", row=" + Bytes.toStringBinary(searchRow)); }
byte[] value = startRowResult.getValue(HConstants.CATALOG_FAMILY,
HConstants.REGIONINFO_QUALIFIER);
if (value == null || value.length == 0) { throw new IOException("HRegionInfo was null or empty in Meta for " + Bytes.toString(tableName) + ", row=" + Bytes.toStringBinary(searchRow)); }

可以发现在扫描MetaScanner,rowkey所在的范围在Meta 表中不存在;通过RPC定位到服务端的实现




HRegion中:


public Result getClosestRowBefore(final byte [] row, final byte [] family)

  throws IOException {

    if (coprocessorHost != null) {

      Result result = new Result();

      if (coprocessorHost.preGetClosestRowBefore(row, family, result)) {

        return result;

      }

    }

    // look across all the HStores for this region and determine what the

    // closest key is across all column families, since the data may be sparse

    checkRow(row, "getClosestRowBefore");

    startRegionOperation();

    this.readRequestsCount.increment();

    try {

      Store store = getStore(family);

      // get the closest key. (HStore.getRowKeyAtOrBefore can return null)

      KeyValue key = store.getRowKeyAtOrBefore(row);

      Result result = null;

      if (key != null) {

        Get get = new Get(key.getRow());

        get.addFamily(family);

        result = get(get, null);

      }

      if (coprocessorHost != null) {

        coprocessorHost.postGetClosestRowBefore(row, family, result);

      }

      return result;

    } finally {

      closeRegionOperation();

    }

  }

在 KeyValue key = store.getRowKeyAtOrBefore(row);中获得了Meta表的rowkey,但是在后续的实现中


     if (key != null) {

        Get get = new Get(key.getRow());

        get.addFamily(family);

        result = get(get, null);

      }

获得空的result导致了这个问题;

为什么会存在这个现象。




先讲一下HBase 的MVCC的原理,

MVCC是保证数据一致性的手段,HBase在写数据的过程中,需要经过好几个阶段,写HLog,写memstore,更新MVCC;

只有更新了MVCC,才算真正memstore写成功,其中事务的隔离需要有mvcc的来控制,比如读数据不可以获取别的线程还未提交的数据。

1、put、delete数据都会调用applyFamilyMapToMemstore

HRegion中


private long applyFamilyMapToMemstore(Map<byte[], List<KeyValue>> familyMap,

    MultiVersionConsistencyControl.WriteEntry localizedWriteEntry) {

    long size = 0;

    boolean freemvcc = false;




    try {

      if (localizedWriteEntry == null) {

//开始一个写memstore,mvcc中的memstoreWrite++,并add待write pending队列中

        localizedWriteEntry = mvcc.beginMemstoreInsert();

        freemvcc = true;

      }




      for (Map.Entry<byte[], List<KeyValue>> e : familyMap.entrySet()) {

        byte[] family = e.getKey();

        List<KeyValue> edits = e.getValue();




        Store store = getStore(family);

        for (KeyValue kv: edits) {

          kv.setMemstoreTS(localizedWriteEntry.getWriteNumber());

          size += store.add(kv);

        }

      }

    } finally {

      if (freemvcc) {

        mvcc.completeMemstoreInsert(localizedWriteEntry);

      }

    }




     return size;

   }




  mvcc.completeMemstoreInsert,更新mvcc 的memstoreRead,也就是可以读的位置, 并通知readWaiters.notifyAll(),释放因flushcache调用waitForRead引起的阻塞;

waitForRead参见以下代码:

       public void waitForRead(WriteEntry e) {

    boolean interrupted = false;

    synchronized (readWaiters) {

//小于,表示还有写未提交

      while (memstoreRead < e.getWriteNumber()) {

        try {

          readWaiters.wait(0);

        } catch (InterruptedException ie) {

          // We were interrupted... finish the loop -- i.e. cleanup --and then

          // on our way out, reset the interrupt flag.

          interrupted = true;

        }

      }

    }

    if (interrupted) Thread.currentThread().interrupt();

  }





2、  在flushcache的过程中,获取到memstore中的keyvalues后,会调用mvcc.waitForRead(w)(因memstore所有的keyvalue,包括还未真正提交的,所以要等待其他事务提交后,才可以进行后续的flush操作,保证事务的一致性。



      w = mvcc.beginMemstoreInsert();


      mvcc.advanceMemstore(w);

    mvcc.waitForRead(w);




3、scan数据


在RegionScannerImpl.next方法实现中:


    public synchronized boolean next(List<KeyValue> outResults, int limit)

        throws IOException {

      if (this.filterClosed) {

        throw new UnknownScannerException("Scanner was closed (timed out?) " +

            "after we renewed it. Could be caused by a very slow scanner " +

            "or a lengthy garbage collection");

      }

      startRegionOperation();

      readRequestsCount.increment();

      try {




        // This could be a new thread from the last time we called next().

//this.readPoint在构造的时,初始化(readpoint为当前hregion的mvcc中的memstoreRead,为当前可读的点)和当前线程绑定

        MultiVersionConsistencyControl.setThreadReadPoint(this.readPt);




在MemStore中过滤掉还未提交的事务(新的keyvalue中有最新的point)





    protected KeyValue getNext(Iterator<KeyValue> it) {

      long readPoint = MultiVersionConsistencyControl.getThreadReadPoint();




      while (it.hasNext()) {

        KeyValue v = it.next();

//过滤掉大于当前线程readPoint的keyvalue

        if (v.getMemstoreTS() <= readPoint) {

          return v;

        }

      }




      return null;

    }



纵观MVCC的整个过程,再分析HRegion中的getClosestRowBefore方法实现,

      KeyValue key = store.getRowKeyAtOrBefore(row);

这个调用不会进行MVCC的控制,可以读到memstore中所有的数据

而get方法是会进行MVCC进行控制的,所以一种可能情况是在get调用的时, store.getRowKeyAtOrBefore(row)读到的key值还未提交,

所有都过滤掉了,查询范围为null。
分享到:
评论

相关推荐

    阿里云HBase备份恢复的原理以及实践.pdf

    阿里云HBase备份恢复的原理以及实践.pdf

    HBase数据库设计.doc

    HBase的模式Schema设计的一些概念和原则 5 1)模式的创建与更新 5 2)列族的数量 6 3)行键设计RowKey 6 5. HBase的拓扑结构是什么? 7 1)拓扑结构 7 2)HBase与ZooKeeper的关系是什么? 7 3)HBase的内部结构管理...

    hbase原理和设计

    hbase原理和设计,包括二级索引,rowkey设计,常见的坑.

    hbase 学习 hbase原理 hbase资料

    hbase 学习 hbase原理 hbase资料 ,呕心沥血整理的。很实用,不适用可拍砖。。

    hbase 表设计

    hbase 数据模型,表结构设计 。。。。。。。。。。。。。。。。。。。。。。。

    HBase的工作原理及使用介绍

    里面包含HBase非关系数据库的工作原理,使用它的优点,缺点.

    HBase的原理与实验

    描述的Hbase的原理,安装已经实现的API,是新手入门的不错教材。值得研究

    hbase的Rowkey设计方案.pdf

    hbase的Rowkey设计⽅案 1.1 hbase的概述 的概述 HBase由于其... 1.2 hbase的设计原则以及解决⽅法 的设计原则以及解决⽅法 1.3 预分区 预分区 1.3.1 什么是预分区 什么是预分区 HBase表在刚刚被创建时,只有1个分区

    Hbase 表设计与操作

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

    HBase原理及实例

    HBase原理及实例

    HBase 基本原理

    HBase 基本原理,出版于 2014,HBase is a NoSQL database that primarily works on top of Hadoop. HBase is based on the storage architecture followed by the BigTable. HBase inherits the storage design ...

    HBASE架构和原理解析

    本文档图文并茂地详细的描述了HBASE列式数据的架构和原理,是HBASE入门不错的的资料

    深入学习hbase原理资料整理

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

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

    这本书对于想学习大数据Hbase的程序爱好者非常有用,深入介绍了从Hbase原理、生态圈到项目中架构设计和相关问题优化的各方面

    HBase中Coprocessor的介绍以及实际业务场景中的使用.pdf

    讲师:陈杨——快手大数据高级研发工程师 ...内容概要:(1)讲解hbase coprocessor的原理以及使用场景,(2) coprocessor整个流程实战,包括开发,加载,运行以及管理(3)结合1,2分析coprocessor在rsgroup中的具体使用

    关于hbase表结构的知识点

    hbase表结构设计,新建表,查询表语句,删除表数据,删除表的例子。

    nosql&hbase;原理

    Nosql&hbase;原理,深度分析了为什么要用hbase?hbase的优缺点,适用场景

    HBase in Practise: 性能、监控和问题排查

    HBase在不同版本(1.x, 2.x, 3.0)中针对不同类型的硬件(以IO为例,HDD/SATA-SSD/PCIe-SSD/Cloud)和场景(single/batch, get/scan)做了(即将做)各种不同的优化,这些优化都有哪些?如何针对自己的生产业务和...

    hbase分析报告 原理分析

    hbase分析 原理分析 详细分析 bigtable解析

    HbaseTemplate 操作hbase

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

Global site tag (gtag.js) - Google Analytics