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

来源:互联网 发布:如何用php打开文件夹 编辑:程序博客网 时间:2024/05/18 12:32

上一个章节将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 过程到此结束。