hbase 源代码分析(6)get 过程 详解

上一个章节将getregionLocator的客户端分析完了,服务端就是一个scan方法,这个等到分析SCAN的时候再做说明。

上一章:hbase 源代码分析(5)regionLocator 获取region过程 详解
http://blog.csdn.net/chenfenggang/article/details/75041244

这一章节将分析GET过程。

**GET过程,
1)找到zk,拿到MATA里的RegionService地址。
2)访问第一个RegionService,获得表的region的ServiceName。
3)访问第二个RegionService,
4) 查看menStore里有没有数据。
5)否则去StoreFile 里找。这个存储在HDFS。所以需要加载HFile到内存中。**

入口:

 Result result = htable.get(new Get("".getBytes()));

客户端的调用:

private Result get(Get get, final boolean checkExistenceOnly) throws IOException {

    .........

       RegionServerCallable<Result> callable = new RegionServerCallable<Result>(this.connection,
          getName(), get.getRow()) {
        @Override
        public Result call(int callTimeout) throws IOException {
          ClientProtos.GetRequest request =
            RequestConverter.buildGetRequest(getLocation().getRegionInfo().getRegionName(), getReq);
          PayloadCarryingRpcController controller = rpcControllerFactory.newController();
          controller.setPriority(tableName);
          controller.setCallTimeout(callTimeout);
          try {
            ClientProtos.GetResponse response = getStub().get(controller, request);
            if (response == null) return null;
            return ProtobufUtil.toResult(response.getResult(), controller.cellScanner());
          } catch (ServiceException se) {
            throw ProtobufUtil.getRemoteException(se);
          }
        }
      };
      return rpcCallerFactory.<Result>newCaller(rpcTimeout).callWithRetries(callable,
          this.operationTimeout);
    }

这个里面包含了
1)找到zk,拿到MATA里的RegionService地址。
2)访问第一个RegionService,获得表的region的ServiceName。
因为这个是getregionLocator。所以将不分析了。

直接调用caller.call()

ClientProtos.GetResponse response = getStub().get(controller, request);

这个直接通过clientProtos访问RSRPCService。

然后会转到HRegion里去,然后将get变成scan(get)

 // pre-get CP hook
    if (withCoprocessor && (coprocessorHost != null)) {
       if (coprocessorHost.preGet(get, results)) {
         return results;
       }
    }
    Scan scan = new Scan(get);
    RegionScanner scanner = null;
    try {
      scanner = getScanner(scan);
      scanner.next(results);
    } finally {
      if (scanner != null)
        scanner.close();
    }
    // post-get CP hook
    if (withCoprocessor && (coprocessorHost != null)) {
      coprocessorHost.postGet(get, results);
    }

这里前后有两个钩子,可以自己去实现协处理,实现Region Coprocessor就行
在初始化的时候指定了为StoreScaner

   for (Map.Entry<byte[], NavigableSet<byte[]>> entry : scan.getFamilyMap().entrySet()) {
          Store store = stores.get(entry.getKey());
          KeyValueScanner scanner;
          try {
            scanner = store.getScanner(scan, entry.getValue(), this.readPt);
          } catch (FileNotFoundException e) {
            throw handleFileNotFound(e);
          }

并将结果放入storeHeap中

   protected void initializeKVHeap(List<KeyValueScanner> scanners,
        List<KeyValueScanner> joinedScanners, HRegion region)
        throws IOException {
      this.storeHeap = new KeyValueHeap(scanners, region.comparator);
      if (!joinedScanners.isEmpty()) {
        this.joinedHeap = new KeyValueHeap(joinedScanners, region.comparator);
      }
    }

在store.getScanner中

 @Override
  public KeyValueScanner getScanner(Scan scan,
      final NavigableSet<byte []> targetCols, long readPt) throws IOException {
    lock.readLock().lock();
    try {
      KeyValueScanner scanner = null;
      if (this.getCoprocessorHost() != null) {
        scanner = this.getCoprocessorHost().preStoreScannerOpen(this, scan, targetCols);
      }
      if (scanner == null) {
        scanner = scan.isReversed() ? new ReversedStoreScanner(this,
            getScanInfo(), scan, targetCols, readPt) : new StoreScanner(this,
            getScanInfo(), scan, targetCols, readPt);
      }
      return scanner;
    } finally {
      lock.readLock().unlock();
    }
  }

然后new的过程

 List<KeyValueScanner> scanners = getScannersNoCompaction();
里面
  protected List<KeyValueScanner> getScannersNoCompaction() throws IOException {
    final boolean isCompaction = false;
    boolean usePread = get || scanUsePread;
    return selectScannersFrom(store.getScanners(cacheBlocks, get, usePread,
        isCompaction, matcher, scan.getStartRow(), scan.getStopRow(), this.readPt));
  }

store.getScanners里面。

@Override
  public List<KeyValueScanner> getScanners(boolean cacheBlocks, boolean isGet,
      boolean usePread, boolean isCompaction, ScanQueryMatcher matcher, byte[] startRow,
      byte[] stopRow, long readPt) throws IOException {
    Collection<StoreFile> storeFilesToScan;
    List<KeyValueScanner> memStoreScanners;
    this.lock.readLock().lock();
    try {
      storeFilesToScan =
          this.storeEngine.getStoreFileManager().getFilesForScanOrGet(isGet, startRow, stopRow);
      memStoreScanners = this.memstore.getScanners(readPt);
    } finally {
      this.lock.readLock().unlock();
    }

这样就添加了storeFilesToScan和memStoreScanners

然后在peek出来,因为storeHeap有序。所以先查看memstore 然后在看StoreFile。

最后匹配

 protected boolean nextRow(ScannerContext scannerContext, byte[] currentRow, int offset,
        short length) throws IOException {
      assert this.joinedContinuationRow == null:
        "Trying to go to next row during joinedHeap read.";
      Cell next;
      while ((next = this.storeHeap.peek()) != null &&
             CellUtil.matchingRow(next, currentRow, offset, length)) {
        this.storeHeap.next(MOCKED_LIST);
      }
      resetFilters();
      // Calling the hook in CP which allows it to do a fast forward
      return this.region.getCoprocessorHost() == null
          || this.region.getCoprocessorHost()
              .postScannerFilterRow(this, currentRow, offset, length);
    }

如果匹配到就可以返回,结束了。

get 过程到此结束。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值