HBase源代码阅读与理解

一、脚本 


start-hbase.sh,hbase-daemon.sh,hbase-daemons.sh,zookeepers.sh,regionservers.sh,hbase,hbase-config.sh
1.1 hbase:hbase命令行入口,最终控制master,regionserver,zookeeper等启动或关闭
1.1.1 hbase shell:执行jruby脚本org.jruby.Main ${HBASE_HOME}/bin/hirb.rb,是hbase命令行接口
1.1.2 hbase master:执行类org.apache.hadoop.hbase.master.HMaster,启动或关闭HMaster
1.1.3 hbase regionserver:执行类org.apache.hadoop.hbase.regionserver.HRegionServer,启动或关闭RegionServer
1.1.4 hbase thrift:执行org.apache.hadoop.hbase.thrift.ThriftServer,启动或关闭thrift服务
注:Thrift是facebook发起的轻量级跨语言的服务框架,现在在apache基金会下。
支持很多语言。Thrift有一个与具体编程语言无关IDL 语言,用来描述服务接口,以及数据交换的格式,存储在.thrift文件中。
然后使用自带的编译器将thrift文件编译成cpp、python等语言的框架代码。
1.1.5 hbase avro
org.apache.hadoop.hbase.avro.AvroServer
Avro 是一个数据序列化系统。
Avro 提供了:
    * 丰富的数据结构。
    * 一个简约的、快速的、二进制数据格式。
    * 一个容器文件,用于存储持久数据。
    * 远程过程调用(RPC)。
    * 和其他动态语言的简单集成。存取数据文件或者使用 RPC 协议的时候不需要生成代码。代码生成只是作为静态类型语言的一个可选的优化项。
1.1.6 migrate:执行org.apache.hadoop.hbase.util.Migrate,貌似系统迁移的功能
1.1.7 zookeeper :执行org.apache.hadoop.hbase.zookeeper.HQuorumPeer,启动或关闭zookeeper服务
1.2 start-hbase.sh 启动hbase。

    启动过程为:先调用hbase-daemons.sh启动zookeeper,再调用hbase-daemon.sh启动master,最后调用hbase-daemons.sh启动regionserver
1.3 hbase-daemons.sh:执行regionservers.sh,从${HBASE_CONF_DIR}/regionservers读取 regionserver列表,ssh到每台host上调用其hbase-daemon.sh脚本,在后台启动regionserver;执行 zookeepers.sh,调用org.apache.hadoop.hbase.zookeeper.ZKServerTool从classpath 下读取zoo.cfg中的server列表,ssh到每台host上调用其hbase-daemon.sh脚本,在后台启动zookeeper;
1.4 hbase-daemon.sh:包装hbase master,regionserver,zookeeper等服务从后台启动

二、HMaster:实现master的功能

A.负责分配region到regionserver,检测新增或失败的regionserver,与regionserver交互,regionserver间的负载均衡等;
B.处理shcema的变更;
C.实现ZooKeeper的Watcher接口,与zookeeper集群交互
2.1 master启动过程初始化,构造HMaster实例
    --minServers=:指定最少的RegionServers数,默认为10    

    根据参数hbase.cluster.distributed分local和distribute模式,这里主要考虑distribute模式下:
    (1)设置并检查文件系统路径。(checkRootDir方法)
       a.如果文件系统处于安全模型,则一直等待直到退出安全模式
       b.若root路径不存在则会创建该目录,并将当前hbase的文件格式版本号写入hbase.version中,并再下一次启动是会检查是否与当前hbase版本支持的文件格式版本一致。
       c.检查root Region是否存在,即-ROOT-目录是否存在(root region也是当做一个table来统一处理的)。如果不存在,则创建root region和第1个meta region。root region:regionId=0,tableName=-ROOT-,仅有一个info的Column Family;meta region:regionId=1,tableName=.META.,有一个info和historian两个Column Family
       d.将meta做为root region的user region加入其中(有点拗口)。         
    (2)获取master的地址,并创建一个HBaseServer的实例提供RPC服务    
    (3)创建一个连接                
    (4)读取classpath下配置的 hbase.zookeeper.property.clientPort和hbase.zookeeper.quorum,连接zookeeper集 群:创建ZooKeeper实例,并增加Watcher(HMaster)设置/hbase,/hbase/root-region-server, /hbase/rs,/hbase/master,/hbase/master/shutdown等hbase存储在zookeeper中信息的路径,将 master地址写入/hbase/master(若该Znode存在,则等待直到该节点被删除。
    (5)建立RegionServerOperation队列
    (6)启动ServerManager管理region servers的信息
    (7)启动RegionManager分配region到region servers,并管理root,meta等状态

2.2 master执行过程,启动线程,执行Thread.run()        
    (1)将master加入集群:
       从zookeeper的hbase/root-region- server读取root region所在的regionserver;读取所有regionserver地址,若没有regionserver则可能是一个新启动的集群,调用 HLog.splitLog(this.rootdir, logDir, oldLogDir, this.fs, getConfiguration());
    (2)启动服务线程:
       启动RegionManager的root和meta region的扫描线程,初始扫描后,应知道所有region的分配信息;而region每次分裂后也应通知master,并分配region给新的 regionserver;但master可能丢失该split信息,因此周期性的扫描root和meta region以检测丢失的split信息及regionserver的死亡信息;启动一个Jetty Server,处理http请求;启动RPC服务。

三、HRegionServer

HRegionServer:管理regions,并向HMaster报告自己状态        
3.1 regionserver启动过程
    (1)读取一些配置:机器名,端口,客户端重试次数,与master交互间隔,rpc超时
    (2)创建Worker线程处理来自master的请求
    (3)创建一个HBaseServer的实例提供IPC服务以处理Client的请求
    (4)创建HServerInfo实例保持regionserver信息:地址,机器名,监听端口等
    (5)创建Flush缓存的线程
    (6)创建Compact和Split region的线程
    (7)创建归档(roll)HLog的线程
    (8)定期检查regions是否需要major compaction线程
    (9)regionserver与外部client交互时,会申请一些资源,当外部client失败后需释放这些资源。创建Leases线程来处理这个任务。
    (10)创建ZooKeeper实例,以连接zookeeper集群,并增加/hbase/master节点的Watcher
    (11)申请一部分heap空间(4个byte数组,每个5M,共20M),保留下来,在发生OOME时再释放以从异常中恢复
    (12)启动regionserver并安装shut down hooks            

3.2 HRegionServer.run()    
    (1)向master报告自己的状态:reportForDuty()方法
       从zookeeper的/hbase/master节点获取master地址,通过HBaseRPC获得HMasterRegionInterface接口实现的代理;
       从MemoryMXBean获取内存使用信息,计算其负载,并保存到HServerInfo实例中; 调 用HMasterRegionInterface.regionServerStartup(),告诉master该regionserver已启动,该 接口返回一个MapWritable,包含hbase.regionserver.address,fs.default.name和 hbase.rootdir等master配置信息,以更新本地配置(HBASE-1215);  
    (2)启动一些服务线程    
       在文件系统根目录下.logs建立commit log HLog的实例;后台启动归档(roll)HLog的线程,Flush缓存的线程,Compact和Split region的线程,来自master请求的worker线程,检查regions是否需要major compaction线程
       启动Leases线程;
       启动Jetty Server,处理http请求      
    (3)当服务线程正常运行(isAlive()),则在hbase.regionserver.msginterval间隔后与master交换信息:
       收集regionserver的metrics,包 括:HStore,HStoreFile,索引,所有region的内存大小,block缓存的命中率等信息,regionserver负载信息;通过 PRC向master发送信息HMsg,并返回master的指令,指令类型有:stop regionserver,停止服务用户regions,重启等。

四、HMater和HRegionServer的RPC连接

    

启动master时创建一个Server的实例,利用反射机制提供HMaster的方法调用服务;Server继承自抽象类HBaseServer;HBaseServer通过异步io(nio包)提供了非阻塞的网络连接
4.1 RPC Server的创建及启动过程
    (1)HBaseServer初始化参数:绑定地址,端口,调用队列大小,最大连接数,最大闲置连接数等    
    (2)创建Listener(继承自Thread)实例,使用ServerSocketChannel绑定到监听 端口,并向Selector注册接受新连接事件,对新连接连接,因为采用异步方式处理,所以为新连接创建一个Connection的实例维持连接状态,并 在Selector注册相应的读事件,以读取请求;对读事件,获取对应的Connection对象,由readAndProcess方法读取并处理请求; 处理请求时,创建Call对象,包含连接和RPC调用的具体参数信息,放入一个队列中,等待处理;     
    (3)创建10个Handler线程,互斥的从Call队列中取出Call的实例,传入参数调用call方法进行RPC调用(该方法由Server实现);将处理完成的结果放入Call对应Connection的回复队列中,并向Selector注册写回复请求
    (4)创建Responder实例线程;该线程获取写回复请求,执行异步写,一次性回复一个Connection的所有Call调用结果
4.2 HRegionServer访问master的RPC:

    在启动regionservre时,采用代理模式创建了接口HMasterRegionInterface的一个本地代理,在调用接口方法时,委托给 Invoker对象的invoke方法,该方法又通过HBaseClient作为客户端向HBaseServer发送请求,并获取返回结果
4.3 HMaster与HRegionServer交互信息的格式
    (1)HServerInfo:包括服务器地址,端口,主机名,regionserver的负载信息HServerLoad
    (2)HRegionInfo:包括region id,起、止Key,region包含的table信息,是否在线,regionName等
    (3)HMsg:HMaster和HRegionServer通信的指令,master发送给 region server的指令包括:启动指定region;停止指定region;分裂region;compact region;停止regionserver;停止指定region而无需回复;停止所有用户region,从region server到master的指令:regionserver正在服务指定region;regionserver已不再服务指定 region;regionserver正在关闭;已停用所有用户region;Flush缓存;运行Major Compaction;分裂指定region
4.4 交互协议
    HRegionServer启动时:
    (1)HRegionServer获取服务端协议版本并比较
    (2)HRegionServer调用HMasterRegionInterface的 regionServerStartup接口,报告该regionserver已启动;HMaster将regionserver的管理都交给 ServerManager;HMaster返回hbase.regionserver.address,fs.default.name和 hbase.rootdir等配置信息         
    (3)然后定期(hbase.regionserver.msginterval)定期调用HMasterRegionInterface的regionServerReport接口报告regionserver的状态,并接受指令
4.5 master对regionserver的管理:ServerManager
    ServerManager维护三个Map记录可用regionserver状况,serversToServerInfo:从serverName到其HServerInfo的映射;
    serversToLoad:从serverName到其最近HServerLoad的映射;
    loadToServers:从HServerLoad到其serverName集合的映射(相同负载的regionserver);
    一个SetdeadServers维护已死亡的regionserver信息;
    (1)regionserver启动后向master报告:
       a.ServerManager的 regionServerStartup方法先检查是否已存在相同的regionserver,若存在且通过startCode判断其是否 stale(???),若stale则终止该regionserver:删除该regionserver对应的HServerInfo、 HServerLoad,加入到deadServers队列,并向master的RegionServerOperation队列中增加一个关闭该 server操作,等待处理
       b.检查该regionserver是否在deadServers队列
       c.然后在zookeeper的/hbase/rs/增加Znode中记录新的regionserver,并向该Znode增加一个ServerExpirer,在该节点被删除后expire该regionserver
       d.serversToServerInfo,serversToLoad,loadToServers增加相应记录
    (2)处理regionserver的heart beat报告(这一部分逻辑比较复杂)
       a.检查该regionserver是否已经dead(与deadServers中的记录进行比较)
       b.第一条HMsg是:regionserver正在关闭,从 serversToServerInfo中删除该regionserver;调用RegionManager,使该regionserver上的所有 meta和root region下线;检查是否有root和meta region正在该server启动,有则重新分配该region ;从serversToLoad和loadToServers从删除该regionserver的load信息;然后依次读取后面每条msg,msg类型 必需为:停止region;通过master的RegionManager来管理region,最后向regionserver返回空的HMsg.
       c.第一条HMsg是:MSG_REPORT_QUIESCED,即regionserver关闭所有user regions,则quiescedServers记录该状态regionserver的数据;当master接受到shutdown请求时,而所有 regionserver仅服务metar regions则关闭master
       d.若master已关闭,则返回REGIONSERVER_STOP的msg
       e.若serversToServerInfo中查不到该regionserver,也向regionserver发送REGIONSERVER_STOP的msg
       f.前面处理掉所有异常情况,然后调用processRegionServerAllsWell 处理regionserver的HMsg:更新serversToServerInfo,serversToLoad,loadToServers中 regionserver对应的信息;依次处理每条HMsg:regionserver正在处理open指定region的请求:累加该指令次数 regionserver已open指定region:若region被重复打开了,则回复regionsever关闭;是root region,则从未分配region列表中删除,并记录root region所在regionserver地址;非root region,设置状态为open,向RegionServerOperationQueue添加ProcessRegionOpen操作,连 接至该region的meta region所在regionserver,该regionserver客户端获得HRegionInterface的代理,put该region的信息 到meta region中(key为region名,CATALOG_FAMILY下有主机和端口、startCode两列);若region是meta region,则加入RegionManager中的扫描队列中。regionserver已关闭指定region:如果是root region则清理RegionManager中roo向master的RegionServerOperationQueue中增加ProcessRegionClose操作:MSG_REPORT_SPLIT,MSG_REPORT_SPLIT_INCLUDES_DAUGHTERS,regionserver分裂region操作:都委托给RegionManager
   (3)ServerMonitor线程,定期dump deadServers和regionserver数量及每个regionserver的平均服务region数量
4.6 regionserver处理master返回的HMsg:regionserver将master返回的消息放入一队列中,由其worker线程从队列中依次取出并处理
   (1)处理MSG_REGIONSERVER_QUIESCE,关闭所有user region:从HRegionServer记录的所有online regions中选出所有user region,每个region启动一个线程进行执行关闭
   (2)MSG_REGION_OPEN,打开指定region:若整个集群的root region还没打开,则不处理该指令,并重新放回队列中;                    
   (3)MSG_REGION_CLOSE,关闭指定region:从online regions中选出要关闭的region,关闭该region,并给master回复已关闭的信息
   (4)MSG_REGION_SPLIT,分裂指定region:先flush缓存数据;设置region的标识变量splitRequest为true;region放入CompactSplitThread线程的compactionQueue队列中等待分裂
   (5)MSG_REGION_MAJOR_COMPACT和MSG_REGION_COMPACT:region放入CompactSplitThread线程的compactionQueue队列中等待Compaction
   (6)MSG_REGION_FLUSH:flush指定region 

五、HMaster对HRegion的管理

HMaster对HRegion的管理:master将region的分派,状态管理等工作委托给RegionManager
   (1)RegionManager成员变量:rootRegionLocation,root region所在regionserver地址;rootScannerThread和MetaScanner,root及meta region的扫描线程;numberOfMetaRegions,meta regions数量由rootScannerThread设置;onlineMetaRegions,在线的meta regions;regionsInTransition,记录正在状态变化中的region,region的状态有:
      UNASSIGNED-等待分配到server
      PENDING_OPEN-告诉server打开,但还未完成
      OPEN-已打开region,但尚未在meta region中标识
      CLOSING-已将close msg放入队列中,但还尚未发送到regionserver
      PENDING_CLOSE-已将regionserver发送给regionserver
      CLOSED-已关闭region,但尚未在meta region中标识
maxAssignInOneGo,一次分配给一个regionserver的最多region数量;LoadBalancer,负责 regionserver间负载均 衡;regionsToSplit,regionsToCompact,regionsToMajorCompact,regionsToFlush,需 split/compact/MajorCompact/Flush的region
   (2)RegionManager工作流程:
      HMaster初始化时创建RegionManager实例;
      清除RegionManager中root region的地址及状态信息,设置root region状态为UNASSIGNED并加入regionsInTransition中;

      HMaster启动各种后台服务时,RegionManager后台启动rootScannerThread和metaScannerThread线程;    
      regionserver向master报告时,ServerManage在regionServerReport方法中调用RegionManager来处理跟region相关的msg.   
    (3)RegionManager处理各种Region相关HMsg    
       a.regionserver正在关闭
         RegionManager关闭该 regionserver上的所有region,包括root,meta和user region,并对root meta和online的user regionr重新分配,对offline user region从regionsInTransition删除其状态信息
       b.regionserver已open指定region
         RegionManager判断该 region是否重复分配了,重复分配则返回关闭该region指令;若open的是root region,则在master的ServerConnection和RegionManager中记录root region所在地址;若open user region,具体操作参见ServerManager        
       c.regionserver已关闭指定region:
         关闭root region               

         关闭meta region:从RegionManager的onlineMetaRegions中删除该region;
         regionsInTransition中设置该region为CLOSED;
         向master的RegionServerOperationQueue中增加ProcessRegionClose操作:往meta中写入该region offline状态,或若该region需重新分配则RegionManager设置该region待分配状态
       d.regionserver已split某个region:    
         读取连续的后两条HMsg从中取出分裂产生的两个HRegionInfo;
         从regionsToSplit和regionsToCompact中删除被分裂的HRegionInfo;
         从onlineMetaRegions中查找应包含新region的meta region,并尝试从对应的regionserver中读取新region,若存在则不做处理,不存在则将新region设置成待分配状态;
         若meta region被分裂,则从onlineMetaRegions中删除掉该region,并增加meta region的数量numberOfMetaRegions;
    (4)组织返回给regionserver的HMsg:
       a.对一个标记为需Close的region,增加一条MSG_REGION_CLOSE的HMsg,并在中regionsInTransition设置其状态为PENDING_CLOSE
       b.若正执行open region的数量少于hbase.regions.nobalancing.count指定的值,则从regionsInTransition中获取待分配的region(root region优先)    
       c.若无region分配给该regionserver,则比较 该regionserver的region负载数量和整个集群的平均负载+slop系数(由参数hbase.regions.slop指定),由一算法 (balanceFromOverloaded和balanceToLowloaded方法),计算该regionserver需close的 region数量,并从负载最严重的region中选择指定数量的非root、meta region和不在regionsInTransition中的region,发出HMsg在该regionserver中close这些region, 并设置状态为PENDING_CLOSE
       d.综合考虑多个整个集群的负载,    将需分配的region分配到多个regionserver:
         通过ServerManager找出负载最轻的那些regionserver,分摊一些region到这些regionserver;
         doRegionAssignment方法分配一个region到指定regionserver,设置状态状态为PENDING_OPEN,并发送MSG_REGION_OPEN消息;
       e.从regionsToCompact,regionsToSplit,regionsToFlush,regionsToMajorCompact中获取需要执行对应操作的region并发送对应HMsg                   
    (5)MetaScanner和RootScanner线程                
       这两个线程都继承自BaseScanner,通过初始化时扫描 root和meta region可以知道所有的region并进行分配;当分裂一个region时,regionserver会通知master分配新region,但 master可能会丢失这些分裂信息,而新region通常没有regionserver的信息,因此周期性地扫描发现这些新region并进行分配。
       a.RootScanner运行时机:master收到regionserver的root region被open指令;首次扫描后定期自动扫描,扫描过程描述:
         从RegionManager获取root region所在rs地址;
         通过master的ServerConnection获取HRegionInterface接口代理,遍历root region内所有meta region的记录;
         检查region对应的HServerInfo是否存在,不存在则表示尚未分配rs,加入到regionsInTransition,设置状态为UNASSIGNED;
         检查所有已分裂的parent,    
       b.MetaScanner运行时机:当一个meta region上线;定期自动扫描上线的meta region;扫描过程逻辑类似RootScanner

六、数据模型HTableDescriptor

HBase中表结构由HTableDescriptor描述(包括HColumnDescriptor),对表的新增\修改\删除操作在接口HMasterInterface中定义,而该接口由HMaster实现
    (1)HTableDescriptor包含:
       表名,byte[]和String格式;
       表的元信息,以key-value形式存储,包括文件最大的大小(默认256M)、是否只读、flush时内存占用大小(默认64M)、是否root或meta region、DEFERRED_LOG_FLUSH;
       表的各Family描述HColumnDescriptor;   
    (2)HColumnDescriptor:描述column family的信息,包括:
       压缩格式(不压缩,仅压缩value,压缩block中的一系列记录);
       数据的版本数量;
            block的大小           

            是否在内存中;
            是否cache block;
            是否使用bloomfilter;
            cell内容的存活时间(ttl);
            是否复制。
            当一个column family创建后,其参数不能修改,除非删除掉该column family后新建一个,但删除column family也会删除掉该column family下的数据.另外,HTableDescriptor中包含ROOT_TABLEDESC和META_TABLEDESC两个实例以描述 root和meta表:
            ROOT_TABLEDESC包含一个info的column family,META_TABLEDESC包含一个info和historian两个column family
    (3)建表过程(HMaster的createTable方法):若指定了splitKeys则为该table按指定键初始创建多个region,否则仅创建一个region
       a.为table创建HRegionInfo
       b.判断是不是所有的meta region都online(由RegionManager的MetaScanner扫描线程分配meta region)
       c.判断serverManager是否有足够regionserver来创建table               

       d.根据步骤a中新建的HRegionInfo创建table:
         从RegionManager的 onlineMetaRegion查找该HRegionInfo应放入哪一个meta region中:在onlineMetaRegion中查找仅比regionName小的meta region,而regionName由tableName,起始Key,和regionId(root为0,meta为1,user当前时间)组成,同 过master的ServerConnection获取HRegionInterface代理连接到该meta region,并查找对应该table为Key的记录是否存在,若存在则报错该表已存在,由RegionManager根据HRegionInfo创建新 的user region:在rootDir目录下新建以tableName为名的目录,在tableName目录下新建一个region的目录(经编码后的 regionName),并新建一个HRegion对象
         将region对应记录放入对应meta region中;
         设置该region状态为未分配,等待分配给regionserver.
    (4)对表的其它操作:disable,enable,delete,这些操作封装在继承自TableOperation的类中
       该类先获得要操作表的所有meta region,扫描这些meta region中所有该表的user region信息并做相应处理,最后处理meta region。

七、数据存储

regionserver负责region内数据的存储及处理客户端的读写请求:
    写请求:当regionserver接受到写请求,先写入一个WAL(write-ahead log) HLog中(同一regionserver的所有log写入同一文件中);然后再写入缓存HStore中;
    读请求:先检查HStore中是否存在被请求数据,不存在则读HFiles
    Flush缓存:当缓存达到配置的大小,则flush到磁盘,写入到新的HFile,并在HLog中做一个标记。(当重做该日志时,忽略上次标记前的记录)Flush时regionserver仍会将读写请求挂起,直至新的HFile产生成功
    Compaction:当flush产生的MapFile数量过多时,会运行compaction合并多个HFile并产生新的Map,以减少文件数量并清除过期和已被删除数据。合并的形式为:
        minor compaction,合并近期产生的几个HFile
        major compaction,合并所有HFile
    Split:当一个region的所有HFiles大小超过指定值(256M),则将父region分为两半,但子region仍从父的MapFile读 取。当一个子region触发了compaction,则会复制数据到自己的目录,当两个子region均执行过compaction,父region将 会被回收由此可见,HBase数据有三种不同存储:HLog,HStore和HFile,并由HRegion管理
    (1)写(Put)过程:
       HRegionServer实现HRegionInterface接口,该接口定义了对region读写操作的接口,客户端获取该接口在本地的代理,调用put系列方法写入数据;
       a.首先,HRegionServer检查该regionserver是否正在关闭、文件系统是否可用
       b.从onlineRegions中获得要写入的 HRegion,并检查该regionserver上所有region的使用的缓存大小是否超过上限,则逐个flush占用内存最大的region,并将 该region加入compactSplitThread线程的队列中以等待compact           

       c.调用HRegion的put方法写入数据
       d.检查HRegion是否处于只读模式
       e.检查HRegion的Memstore大小是否超过hbase.hregion.memstore.flush.size * hbase.hregion.memstore.block.multiplier,若超过了则请求flush并阻塞写操作
       f.doMiniBatchPut方法写入数据,对每个Put,先根据HRegionInfo检查是否存在对应的column family
       g.获取与要操作的行对应的Lock:若Client提供了Lock,则判断给的LockId是否存在对应的行;Client未提供Lock,则产生一个lock,并保存(internalObtainRowLock方法)
       h.设置插入cell的value的timestamp(updateKVTimestamps方法)
       i.将Put操作写入到WALEdit(Write ahead log),并append到HLog中(addFamilyMapToWALEdit和HLog.append方法)
       j.写入到memstore中,由ReadWriteConsistencyControl保持读写一致性,调用Store.add方法
       k.释放锁并返回写入数据所占空间的大小 
    (2)读(Get)过程:HRegionServer实现HRegionInterface接口,该接口提供get方法
       a.首先,HRegionServer检查该regionserver是否正在关闭、文件系统是否可用
       b.从onlineRegions中获得要读取的HRegion,调用HRegion的get方法
       c.若Get设置了column family,检查是否存在;否则读取HTableDescriptor中所有的column family
       d.根据Get创建对应Scan实例,设置startRow、stopRow、filter、maxVersions、TimeRange等(Get操作对应的Scan实例startRow=stopRow)
       e.HBase定义了两个接口InternalScanner和 KeyValueScanner,InternalScanner用于在regionserver上读取下一行指定列的所有键值对 KeyValueScanner用于从各种存储中读取下一个键-值对。在查询中涉及到各个实现见下图:
HBase源代码阅读与理解    RegionScanner:实现InternalScanner接口,它对要扫描的column family对应的Store创建KeyValueScanner实例(StoreScanner)(每个column family中的列存储在同一Store中),并将这些StoreScanner的实例交给KeyValueHeap管理;调用其next(List results)方法时,委托给各个column family的StoreScanner。
    StoreScanner:实现InternalScanner和KeyValueScanner接 口,创建对StoreFile和MemStore进行扫描的KeyValueScanner实例(StoreFileScanner和 MemeStore),并将这些Scanner交给KeyValueHeap管理,而StoreFileScanner对HFile文件的读取又交给了 HFileScanner。

相关推荐