HBase源代码-7-数据存储

7.存储模型
        regionserver负责region内数据的存储及处理客户端的读写请求:
        写请求:当regionserver接受到写请求,先写入一个WAL(write-ahead log) HLog中(同一regionserver的所有log写入同一文件中);然后再写入缓存HStore中;
        读请求:先检查HStore中是否存在被请求数据,不存在则读MapFiles
        Flush缓存:当缓存达到配置的大小,则flush到磁盘,写入到新的MapFile,并在HLog中做一个标记。(当重做该日志时,忽略上次标记前的记录)   
                        Flush时regionserver仍会将读写请求挂起,直至新的MapFile产生成功
        Compaction:当flush产生的MapFile数量过多时,会运行compaction合并多个MapFile并产生新的Map,以减少文件数量并清除过期和已被删除数据。
                        minor compaction,合并近期产生的几个MapFile
                        major compaction,合并所有MapFile
        Split:当一个region的所有MapFiles大小超过指定值(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用于从各种存储中读取下一个键-值对。在查询中涉及到各个实现见下图:
           
            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

猜你喜欢

转载自run-xiao.iteye.com/blog/780525
今日推荐