HBase源码系列(五)Get、Scan在服务端是如何处理的?
来源:互联网 发布:阿里java面试题2016 编辑:程序博客网 时间:2024/05/29 04:06
- Get
- Scan
get 和 scan实际上在服务端的处理,有许多相似的地方,有趣的是get其实也是scan。
Get
直接杀到RSRpcServices的get方法
r = region.get(clientGet);
在HRegion主要做了几件事情:
1、检查get 的rowkey是否在HRegion范围内。
2、如果get请求带了family,就检查这些family在table中是否存在;如果没有携带family,则把table的所有family都加到 get。
3、 scan
Scan scan;if (get.isClosestRowBefore()) { scan = buildScanForGetWithClosestRowBefore(get);} else { scan = new Scan(get);}RegionScanner scanner = null;try { scanner = getScanner(scan); scanner.next(results);} finally { if (scanner != null) scanner.close();}
实例化RegionScanner:如果是反向 scan 就实例化ReversedRegionScannerImpl,否则实例化RegionScannerImpl
if (scan.isReversed()) { if (scan.getFilter() != null) { scan.getFilter().setReversed(true); } return new ReversedRegionScannerImpl(scan, additionalScanners, this);}return new RegionScannerImpl(scan, additionalScanners, this);
遍历scan的所有的family,从family对应的Store中getScanner
for (Map.Entry<byte[], NavigableSet<byte[]>> entry : scan.getFamilyMap().entrySet()) { Store store = stores.get(entry.getKey()); KeyValueScanner scanner = store.getScanner(scan, entry.getValue(), this.readPt); instantiatedScanners.add(scanner); if (this.filter == null || !scan.doLoadColumnFamiliesOnDemand() || this.filter.isFamilyEssential(entry.getKey())) { scanners.add(scanner); } else { joinedScanners.add(scanner); }}
实例化的代码就不贴了,这里要加锁了,如果是反向scan就实例化ReversedStoreScanner,否则实例化StoreScanner。
终于到了StoreScanner核心代码,StoreScanner的构造器中做了几个重要的操作:
1、使用Bloom filter, time range, and TTL过滤掉不需要的StoreFiles。
2、根据key找到特定的scanners。
3、把找到scanners合并到一个KeyValueHeap中,实际上就是把KeyValueScanner放到优先级队列。
开始取出KeyValueHeap的内容,把currentRow的纪录放到Cell列表里面。
do { // We want to maintain any progress that is made towards the limits while scanning across // different column families. To do this, we toggle the keep progress flag on during calls // to the StoreScanner to ensure that any progress made thus far is not wiped away. scannerContext.setKeepProgress(true); heap.next(results, scannerContext); scannerContext.setKeepProgress(tmpKeepProgress); nextKv = heap.peek(); moreCellsInRow = moreCellsInRow(nextKv, currentRow, offset, length); if (moreCellsInRow && scannerContext.checkBatchLimit(limitScope)) { return scannerContext.setScannerState(NextState.BATCH_LIMIT_REACHED).hasMoreValues(); } else if (scannerContext.checkSizeLimit(limitScope)) { ScannerContext.NextState state = moreCellsInRow ? NextState.SIZE_LIMIT_REACHED_MID_ROW : NextState.SIZE_LIMIT_REACHED; return scannerContext.setScannerState(state).hasMoreValues(); } else if (scannerContext.checkTimeLimit(limitScope)) { ScannerContext.NextState state = moreCellsInRow ? NextState.TIME_LIMIT_REACHED_MID_ROW : NextState.TIME_LIMIT_REACHED; return scannerContext.setScannerState(state).hasMoreValues(); }} while (moreCellsInRow);
如果还有结果没有取完就设置ScannerState状态为MORE_VALUES,继续从队列中取出结果;如果结果已经全部取出,设置ScannerState状态为NO_MORE_VALUES
// We are done. Return the result.if (stopRow) { return scannerContext.setScannerState(NextState.NO_MORE_VALUES).hasMoreValues();} else { return scannerContext.setScannerState(NextState.MORE_VALUES).hasMoreValues();}
最后,可能需要纪录下一些统计信息
// do after lockif (this.metricsRegion != null) { long totalSize = 0L; for (Cell cell : results) { totalSize += CellUtil.estimatedSerializedSizeOf(cell); } this.metricsRegion.updateGet(totalSize);}
Scan
RSRpcServices的scan方法,直接就是一大坨代码。
如果scan请求设了ScannerId,就从regionServer直接拿到HRegion。如果没有设置ScannerId,就基于region specifier找到HRegion。
看到了和get相同的部分:
scanner = region.getScanner(scan);
实例化 RegionScannerImpl 类。
在他的构造中,做了几个重要的操作,1、遍历store,并get 到他的KeyValueScanner;2、初始化KVHeap。
scan的核心代码和get的是一样的: scanner.nextRaw(values, scannerContext)。
// 遍历所有的行while (i < rows) { // 每一行中的所有cell,放到List<Cell>中 moreRows = scanner.nextRaw(values, scannerContext); if (!values.isEmpty()) { for (Cell cell : values) { totalCellSize += CellUtil.estimatedSerializedSizeOf(cell); } final boolean partial = scannerContext.partialResultFormed(); // 把List<Cell>封装成Result,并加入到List<Reslut>中。 results.add(Result.create(values, null, stale, partial)); i++; } ...}
将结果包装到ScanResponse
addResults(builder, results, controller, RegionReplicaUtil.isDefaultReplica(region.getRegionInfo()));
- HBase源码系列(五)Get、Scan在服务端是如何处理的?
- hbase源码系列(十二)Get、Scan在服务端是如何处理
- HBase源码系列(四)Put、Delete在服务端是如何处理的?
- Hbase源码研究(二)-------get最终转化为scan来处理(1)
- Hbase源码研究(三)-------get最终转化为scan来处理(2)
- HBase分析之Get、Scan(一)
- HBase的Scan实现源码分析
- go-hbase的Scan模型源码分析
- Hbase里scan的批量处理setCaching
- hbase源码学习之GET操作之get转化为scan
- HBase分析之Get、Scan(二)RegionScanner
- HBase分析之Get、Scan(三)StoreScanner
- 计算机是如何处理中文的(五)
- HBase的scan源码分析客户端部分之整体流程(一)
- hbase-1.2.1之scan、batch操作的源码学习
- hbase系列-HBase Scan类用法
- hbase服务端源码分析
- Ajax与Pjax请求在服务端是如何识别的
- 【问题解决】hadoop datanode无法启动
- 用指针将整型数组的值逆序存放
- Tomcat与Solr4.10整合(Windwow环境)
- 33.笔记 MySQL学习——删除索引
- 【Java】日期&字符串互转
- HBase源码系列(五)Get、Scan在服务端是如何处理的?
- Java并发编程札记-(一)基础-04Thread详解
- 34.笔记 MySQL学习——更改表结构
- 安装部署Elasticsearch并用postman浏览数据
- java事务及隔离级别
- JAVA----定时操作任务
- Python中的作用域规则:最内嵌套作用域规则 和 LEGB
- 35.笔记 MySQL学习——通过SHOW获取数据库元数据
- 大量的QT控件及示例发放