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