UserScan的处理流程分析

本文详细分析了UserScan在HBase中的处理流程,从ClientScanner的生成到RPC调用,深入HRegionServer的scan操作,包括openScanner、RegionScannerImpl的创建以及ScanQueryMatcher的匹配逻辑。讲解了ClientScanner如何获取startkey所在region,以及RegionScannerImpl如何初始化,特别是StoreScanner的生成和匹配过程。通过对ScanQueryMatcher.match方法的分析,展示了如何处理用户扫描时的行和列匹配以及版本控制。
摘要由CSDN通过智能技术生成

UserScan的处理流程分析

前置说明

Userscan是通过clientcp中发起的scanner操作。

Scan中通过caching属性来返回可以返回多少条数据,每次进行next时。

通过batch属性来设置每次在rs端每次nextkv时,可读取多少个kv(在同一行的情况下)

在生成Scan实例时,最好是把familycolumn都设置上,这样能保证查询的最高效.

client端通过生成Scan实例,通过HTable下的如下方法得到ClientScanner实例

publicResultScannergetScanner(finalScan scan)

在生成的ClientScanner实例中的callable属性的值为生成的一个ScannerCallable实例。

并通过callable.prepare(tries!= 0);方法得到此scanstartkey所在的regionlocation.meta表中。

startkey对应的location中得到此locationHRegionInfo信息。

并设置ClientScanner.currentRegion的值为当前的region.也就是startkey所在的region.


通过ClientScanner.nextrs发起rpc调用操作。调用HRegionServer.scan

publicScanResponse scan(finalRpcControllercontroller,finalScanRequest request)



ClientScanner.next时,首先是发起openScanner操作,得到一个ScannerId

通过ScannerCallable.call方法:

if(scannerId== -1L) {

this.scannerId= openScanner();

} else{

openScanner方法:中发起一个scan操作,通过rpc调用rs.scan

ScanRequest request=

RequestConverter.buildScanRequest(

getLocation().getRegionInfo().getRegionName(),

this.scan,0, false);

try{

ScanResponse response= getStub().scan(null,request);

longid =response.getScannerId();

if(logScannerActivity){

LOG.info("Openscanner=" + id+ " for scan="+ scan.toString()

+ "on region " +getLocation().toString());

}

returnid;


HregionServer.scan中对openScanner的处理:

publicScanResponse scan(finalRpcControllercontroller,finalScanRequest request)

throwsServiceException {

Leases.Lease lease= null;

String scannerName= null;

........................................很多代码没有显示

requestCount.increment();


intttl = 0;

HRegion region= null;

RegionScannerscanner =null;

RegionScannerHolder rsh= null;

booleanmoreResults= true;

booleancloseScanner= false;

ScanResponse.Builder builder= ScanResponse.newBuilder();

if(request.hasCloseScanner()){

closeScanner= request.getCloseScanner();

}

introws = 1;

if(request.hasNumberOfRows()){

rows= request.getNumberOfRows();

}

if(request.hasScannerId()){

.................................很多代码没有显示

} else{

得到请求的HRegion实例,也就是startkey所在的HRegion

region= getRegion(request.getRegion());

ClientProtos.Scan protoScan= request.getScan();

booleanisLoadingCfsOnDemandSet= protoScan.hasLoadColumnFamiliesOnDemand();

Scan scan= ProtobufUtil.toScan(protoScan);

//if the request doesn't set this, get the default region setting.

if(!isLoadingCfsOnDemandSet){

scan.setLoadColumnFamiliesOnDemand(region.isLoadingCfsOnDemandDefault());

}

scan.getAttribute(Scan.SCAN_ATTRIBUTES_METRICS_ENABLE);

如果scan没有设置family,region中所有的family当成scanfamily

region.prepareScanner(scan);

if(region.getCoprocessorHost()!= null){

scanner= region.getCoprocessorHost().preScannerOpen(scan);

}

if(scanner ==null){

执行HRegion.getScanner方法。生成HRegion.RegionScannerImpl方法

scanner= region.getScanner(scan);

}

if(region.getCoprocessorHost()!= null){

scanner= region.getCoprocessorHost().postScannerOpen(scan,scanner);

}

把生成的RegionScanner添加到scanners集合容器中。并设置scannerid(一个随机的值),

scannernamescanneridstring版本。添加过期监控处理,

通过hbase.client.scanner.timeout.period配置过期时间,默认值为60000ms

老版本通过hbase.regionserver.lease.period配置。

过期检查线程通过Leases完成。对scanner的过期处理通过一个

HregionServer.ScannerListener.leaseExpired实例来完成。


scannerId= addScanner(scanner,region);

scannerName= String.valueOf(scannerId);

ttl= this.scannerLeaseTimeoutPeriod;

}

............................................很多代码没有显示


Hregion.getScanner方法生成RegionScanner实例流程


publicRegionScannergetScanner(Scanscan)throwsIOException {

returngetScanner(scan,null);

}


层次的调用,此时传入的kvscannerlistnull

protectedRegionScannergetScanner(Scanscan,

List<KeyValueScanner>additionalScanners)throwsIOException {

startRegionOperation(Operation.SCAN);

try{

//Verify families are all valid

prepareScanner(scan);

if(scan.hasFamilies()){

for(byte[] family :scan.getFamilyMap().keySet()){

checkFamily(family);

}

}

returninstantiateRegionScanner(scan,additionalScanners);

}finally{

closeRegionOperation();

}

}


最终生成一个HRegion.RegionScannerImpl实例

protectedRegionScannerinstantiateRegionScanner(Scanscan,

List<KeyValueScanner>additionalScanners)throwsIOException {

returnnewRegionScannerImpl(scan,additionalScanners,this);

}


RegionScanner实例的生成构造方法:

RegionScannerImpl(Scanscan,List<KeyValueScanner>additionalScanners,HRegion region)

throwsIOException {


this.region= region;

this.maxResultSize= scan.getMaxResultSize();

if(scan.hasFilter()){

this.filter= newFilterWrapper(scan.getFilter());

} else{

this.filter= null;

}


this.batch= scan.getBatch();

if(Bytes.equals(scan.getStopRow(),HConstants.EMPTY_END_ROW)&& !scan.isGetScan()){

this.stopRow= null;

} else{

this.stopRow= scan.getStopRow();

}

//If we are doing a get, we want to be [startRow,endRow] normally

//it is [startRow,endRow) and if startRow=endRow we get nothing.

this.isScan= scan.isGetScan()? -1 : 0;


//synchronize on scannerReadPoints so that nobody calculates

//getSmallestReadPoint, before scannerReadPoints is updated.

IsolationLevelisolationLevel= scan.getIsolationLevel();

synchronized(scannerReadPoints){

if(isolationLevel== IsolationLevel.READ_UNCOMMITTED){

//This scan can read even uncommitted transactions

this.readPt= Long.MAX_VALUE;

MultiVersionConsistencyControl.setThreadReadPoint(this.readPt);

} else{

this.readPt= MultiVersionConsistencyControl.resetThreadReadPoint(mvcc);

}

scannerReadPoints.put(this,this.readPt);

}


//Here we separate all scanners into two lists - scanner that providedata required

//by the filter to operate (scanners list) and all others(joinedScanners list).

List<KeyValueScanner>scanners =newArrayList<KeyValueScanner>();

List<KeyValueScanner>joinedScanners= newArrayList<KeyValueScanner>();

if(additionalScanners!= null){

scanners.addAll(additionalScanners);

}

迭代每一个要进行scanstore。生成具体的StoreScanner实例。通常情况下joinedHead的值为null

for(Map.Entry<byte[],NavigableSet<byte[]>>entry :

scan.getFamilyMap().entrySet()){

Storestore =stores.get(entry.getKey());

生成StoreScanner实例。通过HStore.getScanner(scan,columns);

KeyValueScannerscanner =

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值