Hbase-0.98.6源码分析--Put写操作HRegionServer端流程

       在《Hbase-0.98.6源码分析--Put写操作Client端流程》中,介绍了put操作的流程,最后client端是通过MultiServerCallable.call()调用multi()方法来进行rpc请求的。追踪multi()方法,进入ClientProtos.ClientService.BlockingInterface接口的multi()抽象方法,再次追踪该方法,进入实现该方法的HRegionServer实例,查看multi()方法的具体实现:



       这个方法里面还包括了PayloadCarryingRpcController和CellScanner可以看得出来它不只是被Put来用的,但是这些我们不管我们只看Put如何处理就行了。在该方法的3464行调用了getRegion()方法,来获取对应的HRegion,简单看一下:



       分析下getRegionByEncodedName()方法流程,看它如何从当前regionserver中的onlnieRegions中得到请求的region.:

       1.从onlineRegions中取出HRegion实例
       2.如果onlineRegions列表中不包含此region,从movedRegions列表中拿到region,region的moved超时是2分钟,
如果movedRegions列表中能拿到此region,同时move时间超时,并从movedRegions列表中移出引region返回null,
否则返回正在moved的region,如果movedRegions中返回的region不为null,throwRegionMovedException
       3.从regionsInTransitionInRS中获取此region,如果能拿到,同时拿到的值为true,表示region还在做opening操作,
Throw RegionOpeningException
       4.如果以上得到的值都为null,表示此server中没有此region,throw NotServingRegionException
此时基本上只有一个可能,region在做split.或者move到其它server(刚完成move,client请求时不在此server)

      总结下multi()方法的操作:

       1、取出来所有的action(Put),这里主要是put,因为我们调用客户端就是这么调用的,其实别的类型也可以支持,获取他们对应的region。
       2、根据action的原子性来判断走哪个方法,原子性操作走mutateRows,非原子性操作走doNonAtomicRegionMutation方法,我查了一下这个Atomic到底是怎么回事,我搜索了一下代码,发现在调用HTable的mutateRow方法的时候,它设置了Atomic为true,这个是应该是支持一行数据的原子性的,有这个需求的童鞋可以尝试用这个方法,也是可以提交多个,包括Put、Delete操作。

       接下来看doNonAtomicRegionMutation()方法,用于处理非原子性的put/delete/get操作,这是我们常用的方式:




       这里面代码很多,也适配了很多种类型,是个大而全的方法,但是我们这里用到的只是把Put、Delete等的类型转换添加到mutations的列表里,然后走最后的圈出的doBatchOp()这个批量操作,然而这个代码也比较长,简单说一下该方法的思路:

       1、还是得把Put、Delete给转换类型,这里的批量操作只支持全是Delete或者全是Put。
       2、用HRegion.batchMutate方法来执行操作,返回OperationStatus数组,记录每个action的状态,是成功,还是失败,或者是别的状态。
       在batchMutate()里面首先就是检查是否是只读状态,然后检查是否是Meta Region的,是否执行MemStore检查了。


        终于到了最终的Big Boss类,这个类很长很长很长。。。。。。
        1、重要的成员变量

        2、检查Put和Delete里面的列族是否和Region持有的列族的定义相同,有时候我们在Delete的时候是不填列族的,这里它给这个缺的列族来一个KeyValue.Type.DeleteFamily,删除列族的类型。
        3、给Row加锁,先计算hash值做key,如果该key没上过锁,就上一把锁,然后计算出来要写的action有多少个,记录到numReadyToWrite。
        4、更新时间戳,把该action里面的所有的kv的时间戳更新为最新的时间戳,它这里也会把之前的没运行的也一起更新。
  5、给该region加锁,这个时间点之后,就不允许读了,等待时间需要根据numReadyToWrite的数量来计算。


        6、上锁之后,就是Put、Delete等的重点。给这些写入memstore的数据创建一个批次号。


        7、把kv们写入到memstore当中,然后计算出来一个添加数据之后的新的MemStore的大小addedSize。

        MemStore里面有两个kv的集合,调用applyFamilyMapToMemstore()把kv添加到集合里面去。
        8、把kv添加到日志当中,标志状态为成功,如果是用户设置了不写入日志的,它就不写入日志了。
        9、先异步添加日志,这里为什么是异步的,因为之前给上锁了,暂时不能读了。
       10、释放之前创建的锁。

       11、同步日志。
       12、结束该批次的操作。
       Final、同步日志没成功的,最后根据批次回滚MemStore中的操作。
     

  
           

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值