日期:2014-05-16  浏览次数:20642 次

HBase的get过程(一)



?0.90.X的get和scan操作原理上是比较一致的,get操作都变为scan操作。不过在分析之前我们还是从get说起

话不多说首先看看get这个接口,hbase客户端对于get有以下几种:

public Get(byte [] row)
public Get(byte [] row, RowLock rowLock)

?其中rowlock主要是用来保证行的事务性,即每个get是以一个row来标记的一个row中可以有很多family和column

get还有很多函数如addfamily,addcolumn,这里我主要以指定row family column来get数据

?

ok我们来看HTable的get操作

public Result get(final Get get) throws IOException {
    return connection.getRegionServerWithRetries(
        new ServerCallable<Result>(connection, tableName, get.getRow()) {
          public Result call() throws IOException {
            return server.get(location.getRegionInfo().getRegionName(), get);
          }
        }
    );
  }

?这也是一个RPC调用的过程且其返回结果为Result。

1.调用HConnectManger的getRegionServerWithRetries(ServerCallable<T> callable)

callable.instantiateServer(tries != 0);
????????? return callable.call();

这两步主要是找到该get的row所在的region,locateRegion

这个过程以后再来分析,总之就是找到该get所在的region,并与该region所在server通信

我们主要来看RegionServer端的Get操作,主要是region的get操作

?

List<KeyValue> result = get(get);
 private List<KeyValue> get(final Get get) throws IOException {
    Scan scan = new Scan(get);

    List<KeyValue> results = new ArrayList<KeyValue>();

    InternalScanner scanner = null;
    try {
      scanner = getScanner(scan);
      scanner.next(results);
    } finally {
      if (scanner != null)
        scanner.close();
    }
    return results;
  }

?上述这个过程就是region的get过程,我们用下图来进行一个简单的描述

?

每个region中有一个regionscanner,每个regionscanner中维持一个heap的优先级队列,其中包含所有的storescanner,每个storescanner中包含一个Memstorescanner和n个Hfilescanner

进行查找时首先会定位到hfilestore或是memstore,找到这个get的row起始位置

?

在HFile或是memstore中数据视安从小到大进行排序的,排序规则是按keyvalue的大小,row,family,column,timestamp,最后是type。

?



?

上图就是模拟hfile里面keyvalue的一个排序规则。

哪些get的话如果没有指定时间戳的话会返回最近的一个值。,get也可以制定取回的版本数。

如果我们需要取回3个版本如上图所示

首先每个Hfile会定位到该row的起始处位置如此处在这3个Hflie的开头,若指定的column是C1

然后比较这三个文件开头的keyvalue大小,显然第三个R1,cf,c1,9最小,故首先取它

然后该文件指针往下移,重新比较当前指针的最小值,此时第一个文件的R1,cf,c1,8最小故第二个版本取它

然后指针下移继续比较知道满足版本数为止