1. 程式人生 > >hbase 原始碼分析(6)get 過程 詳解

hbase 原始碼分析(6)get 過程 詳解

上一個章節將getregionLocator的客戶端分析完了,服務端就是一個scan方法,這個等到分析SCAN的時候再做說明。

這一章節將分析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 過程到此結束。

相關推薦

hbase 原始碼分析6get 過程

上一個章節將getregionLocator的客戶端分析完了,服務端就是一個scan方法,這個等到分析SCAN的時候再做說明。 這一章節將分析GET過程。 **GET過程, 1)找到zk,拿到MATA裡的RegionService地址。 2)訪問第一

hbase 原始碼分析 15compact 過程

上一個章節分析了spit過程。當時遺留了compact問題沒有分析。這個章節將重點分析一下。 compact流程:  這個流程沒有寫完,涉及都行太多了,都沒有心情寫了。先留著吧, 入口:HStore.java 結束flush之後,會做這樣一個判斷。 p

Mybatis原始碼分析6—— 從JDBC看Mybatis的設計

Java資料庫連線,(Java Database Connectivity,簡稱JDBC)是Java語言中用來規範客戶端程式如何來訪問資料庫的應用程式介面,提供了諸如查詢和更新資料庫中資料的方法。 六步流程: 載入驅動(5.x驅動包不需要這步了) 建立

springcloud feign原始碼分析6——關鍵元件!找一找Feign.Client用的是誰以及居然在這裡就跟ribbon關聯了!

分析完了底層的原始碼,就是用各種預設的bean、配置的bean、配置的引數,構造了一個Feign.Builder,接下來就是基於這個Feign.Builder,還得在這個Builder裡放一個Feign.Client進去。。。 如果你在@FeignClient上,沒有配置u

JDK原始碼分析6ConcurrentHashMap

JDK版本 ConcurrentHashMap原始碼分析 table:預設為null,初始化發生在第一次插入操作,預設大小為16的陣列,用來儲存Node節點資料,擴容時大小總是2的冪次方。 nextTable:預設為null,擴容時新生成的陣列,其大小為原陣列的兩倍。 sizeC

HLS學習HLSDownloader原始碼分析6下載TS檔案片段

下載TS檔案片段 處理完Master PlayList和Media PlayList之後就可以開始下載TS視訊片段了 下載的流程如下: 1、初始化本地的檔名 2、設定本地檔案的訪問許可權 3、建立任務佇列 4、建立PlayList更新執行緒,因為伺服器上的m3u8檔案

hbase 原始碼分析20 總結

放在最後的話 第一次寫這麼長時間的部落格。有點辛苦,主要是白天上班還不能寫。晚上會寫到一兩點。還好沒有放棄,hbase的基本寫完了。之後會不斷補充,完善。 第一次寫,很多地方可能沒有考慮清楚。 第一次寫,帶著學習的目的。不好請大家多擔待。 第一次寫,學到

libevent原始碼分析6--2.1.8--建立和釋放libevent控制代碼event_base的相關函式

一、event_base_new 建立預設的event_base ** * Create and return a new event_base to use with the rest of Libevent. * * @return a new event_ba

Kafka原始碼分析6

六  其他 1、Producer 首先來看org.apache.kafka.clients.producer中的KafkaProducer類實現,org.apache.kafka開頭的包全部是以java實現的,為使用者提供呼叫kafka元件的功能。該類程式碼如下: pub

Netty原始碼分析 ----- read過程 原始碼分析

在上一篇文章中,我們分析了processSelectedKey這個方法中的accept過程,本文將分析一下work執行緒中的read過程。 private static void processSelectedKey(SelectionKey k, AbstractNioChannel ch) {

Netty原始碼分析 ----- write過程 原始碼分析

上一篇文章主要講了netty的read過程,本文主要分析一下write和writeAndFlush。 主要內容 本文分以下幾個部分闡述一個java物件最後是如何轉變成位元組流,寫到socket緩衝區中去的 pipeline中的標準連結串列結構 java物件編碼過程 write:寫佇列 flus

挑戰408——作業系統6——執行緒

20世紀80年代,人們提出了比程序更小,並能獨立執行的基本單位——執行緒。如果說程序的目的是為了讓多個程式彼此之間能夠併發執行,那麼引入執行緒就是為了減少併發執行所付出的時間和空間開銷。從而使得作業系統具有更好的併發性。 執行緒的作用 由於程序是一個資源的擁有者,因此在程序的建立

web前端學習css學習筆記部分6-- 選擇器

9、選擇器詳解 9.1  屬性選擇器   <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</

Linux命令學習6 head命令

head 顯示文字頭部內容 head命令的作用就像它的名字一樣,用於顯示檔案的開頭部分文字。 使用方式 [[email protected] ~]# head [-n number] 檔案 選項與引數: -n :後面接數字,代表顯示幾行的意思 [[e

解讀ASP.NET 5 & MVC6系列6:Middleware

在第1章專案結構分析中,我們提到Startup.cs作為整個程式的入口點,等同於傳統的Global.asax檔案,即:用於初始化系統級的資訊(例如,MVC中的路由配置)。本章我們就來一一分析,在這裡如何初始化這些系統級的資訊。 新舊版本之間的Pipeline區別 ASP.NET 5和之前版本的最大區別是對HT

EasyPR--開發6SVM開發

  在前面的幾篇文章中,我們介紹了EasyPR中車牌定位模組的相關內容。本文開始分析車牌定位模組後續步驟的車牌判斷模組。車牌判斷模組是EasyPR中的基於機器學習模型的一個模組,這個模型就是作者前文中從機器學習談起中提到的SVM(支援向量機)。  我們已經知道,車牌定位模組的輸出是一些候選車牌的圖片。但如何從

Spring原始碼分析之Bean的建立過程

前文傳送門: 1. [Spring原始碼分析之預啟動流程](https://mp.weixin.qq.com/s/bfbPJOlYo2Vz2UTSMWRGkw) 2. [Spring原始碼分析之BeanFactory體系結構](https://mp.weixin.qq.com/s/FDx0hmCp7dEfw

以太坊原始碼解讀6blockchain區塊插入和校驗分析

以太坊blockchain的管理事務: 1、blockchain模組初始化 2、blockchain模組插入校驗分析 3、blockchain模組區塊鏈分叉處理 4、blockchian模組規範鏈更新 上一節分析了blockchain的初始化,這一節來分析blockchain區塊的插入和校驗

比特幣BTC原始碼分析1:地址生成過程

一、生成一個比特幣錢地址 二、根據原始碼整理比特幣地址生成過程 1、取得公鑰PubKey 2、使用 RIPEMD160(SHA256(PubKey)) 雜湊演算法,取公鑰並對其雜湊兩次 3、給雜湊加上地址生成演算法版本的字首 4、對於第二步生成的結果,使用SHA256(SHA256

以太坊ETH原始碼分析1:地址生成過程

一、生成一個以太坊錢包地址 通過以太坊命令列客戶端geth可以很簡單的獲得一個以太坊地址,如下: ~/go/src/github.com/ethereum/go-ethereum/build/bin$geth account new INFO [11-03|20:09:33.219]