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 原始碼分析(6)get 過程 詳解
上一個章節將getregionLocator的客戶端分析完了,服務端就是一個scan方法,這個等到分析SCAN的時候再做說明。 這一章節將分析GET過程。 **GET過程, 1)找到zk,拿到MATA裡的RegionService地址。 2)訪問第一
hbase 原始碼分析 (15)compact 過程
上一個章節分析了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原始碼分析(6)ConcurrentHashMap
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--開發詳解(6)SVM開發詳解
在前面的幾篇文章中,我們介紹了EasyPR中車牌定位模組的相關內容。本文開始分析車牌定位模組後續步驟的車牌判斷模組。車牌判斷模組是EasyPR中的基於機器學習模型的一個模組,這個模型就是作者前文中從機器學習談起中提到的SVM(支援向量機)。 我們已經知道,車牌定位模組的輸出是一些候選車牌的圖片。但如何從
Spring原始碼分析之Bean的建立過程詳解
前文傳送門: 1. [Spring原始碼分析之預啟動流程](https://mp.weixin.qq.com/s/bfbPJOlYo2Vz2UTSMWRGkw) 2. [Spring原始碼分析之BeanFactory體系結構](https://mp.weixin.qq.com/s/FDx0hmCp7dEfw
以太坊原始碼解讀(6)blockchain區塊插入和校驗分析
以太坊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]