问题:
1.hbase的查询block cache,memstore,hfile的过程 
2.hbase的写入wal,memstore,region,hfile,data block的过程
3.upsert和删除数据时,是新增还是修改标志位.
4.假设region server 有10台,salt 加盐5取余, 5个region后,怎么分配机器.
下面的*代表父子类继承关系.

第二节 架构

第三节 启动
程序入口org.apache.hadoop.hbase.master.HMaster.main(String[])->org.apache.hadoop.hbase.master.HMasterCommandLine.run(String[])->
org.apache.hadoop.hbase.master.HMasterCommandLine.startMaster()

第四节 客户端
一.region定位,
理论部分参考<hbase实战> 3.3.2节 如何找到region
1.Table.getScanner(Scan)没有什么操作,主要是构造对象.
2.在数据集遍历时,ResultScanner.iterator()->ClientSimpleScanner*ClientScanner.loadCache()->ScannerCallableWithReplicas.call(int)->RpcRetryingCallerWithReadReplicas.getRegionLocations()->ConnectionImplementation.locateRegion(),传进来的tableName是业务表名,row是rowkey字节编码后的值.先判断是不是定位META表,如果是进入ConnectionImplementation.locateMeta().否则,业务表进入ConnectionImplementation.locateRegionInMeta().
3.业务表进入MetaCache.getCachedLocation().从之前加载的meta表数据缓存中查找业务数据行的region.第一次缓存没有.进入RegionInfo.createRegionName()根据rowkey创建查询meta表的start 和end rowkey,创建规则为取完整表名+,+完整的start rowkey+,.创建查询meta表的scan对象,参数是生成的start,end rowkey,列族是info.
4.这里重复执行了一遍MetaCache.getCachedLocation().?为啥,莫名其妙
5.调用ReversedClientScanner执行scan.遍历meta表的结果集.这时进入ConnectionImplementation.locateMeta()去查询meta表.如图。
查询出来meta表位置在"[region=hbase:meta,,1.1588230740, hostname=qav2,16020,1570609669911, seqNum=-1]".缓存meta表位置到ConnectionImplementation.metaCache属性中.
6.如果是业务表,进入ConnectionImplementation.locateRegionInMeta().获取到缓存中的region位置.返回类似
[region=DATA_CENTER:WAKANDA_GPS,,1570506179712.4e84fa332945e81a410cf1a37c844560., hostname=qav2,16020,1570609669911, seqNum=3426].得到region后,取出server name,向服务器端发出scan请求如下.
{"loadColumnFamiliesOnDemand":null,"startRow":"2234567890150000000015706976010002620601","stopRow":"2234567890150000000015707037770002626901","batch":-1,"cacheBlocks":true,"totalColumns":2,"maxResultSize":2097152,"families":{"0":["JNY_ID","PLATE_NO"]},"caching":1000,"maxVersions":1,"timeRange":[0,9223372036854775807]}.

二.ResultScanner.next()查找下一条数据.
调用hbase.client.ResultScanner.next()进入hbase的jar包查询下一条记录.如下图:

hbase 源码 读流程 hbase 源码解析_源码


(3).hbase.client.ResultScanner.next()->ClientScanner.nextWithSyncCache()->ScannerCallableWithReplicas.call(),在这个方法中获取RegionLocations.调用ScannerCallableWithReplicas.addCallsForCurrentReplica()->ResultBoundedCompletionService.submit(),这里面的newFuture,指向ScannerCallableWithReplicas$RetryingRPC.发起RPC调用.进入RpcRetryingCallerImpl.callWithRetries()。

(4).RpcRetryingCallerImpl.callWithRetries()->

第五节 get/scan执行流程
一.服务端入口为org.apache.hadoop.hbase.regionserver.RSRpcServices.scan().如下图.

hbase 源码 读流程 hbase 源码解析_hadoop_02


二.查找数据,先进入RegionScannerImpl.initializeScanners(Scan, List<KeyValueScanner>)创建一个RegionScannerImpl.

1.在StoreScanner的构造方法中,创建一个ScanQueryMatcher类型的UserScanQueryMatcher.

2.在HStore.getScanners()方法中创建storeFile和memStore的扫描KeyValueScanner类.memStore的扫描器类型为SegmentScanner.

3.进入StoreScanner.seekScanners()开始扫描数据.(直接在StoreScanner的构造方法里做了,够狠).MemStore的seek是查找有序集合。HFile是扫描文件.

4.使用scanner初始化storeHeap, joinedHeap.joinedHeap基本用不到.

三.过滤匹配数据,org.apache.hadoop.hbase.regionserver.HRegion.RegionScannerImpl.nextRaw()->nextInternal()

1.从KeyValueHeap storeHeap 取出一行

2.判断当前行是否是最后一行

3.调用RegionScannerImpl.filterRowKey(Cell)过滤rowkey是否满足需求.

4.调用RegionScannerImpl.populateResult()填充一行结果.

5.根据KeyValueHeap joinedHeap处理一些特殊的filter.

第六节 put/delete执行流程

第七节 存储结构
Region Server下面有若干个Region,每个Region下面有若干的列族,每个列族对应着一个HStore。HFile格式如下图:

hbase 源码 读流程 hbase 源码解析_hfile_03


看HFile文件数据的命令:

./hadoop dfs  -cat /hbase/data/default/emp/049599c82372a473253d26a9b652e56a/'personal data'/ff68604fdbda402aaf10b9d05ec564e7

 看hfile数据

第八节 内存刷磁盘过程