HBase行锁和扫描

HBase的主要客户端接口是由org.apache.hadoop.hbase.client包中的HTable类提供的,通过这个类,用户可以完成向HBase存储和检索数据,以及删除无效数据之类的错做。

所有修改数据的操作都保证了行级别的原子性,这会影响到这一行数据所有的并发读写操作,换句话说,其他客户端或线程对统一行读写操作都不会影响到改行数据的原子性:要么读到最新的修改,要么等待系统允许写入该行修改。写操作中涉及的列的数目不会影响到该行数据的原子性,行原子性会同时保护到所有列。

行锁

在HBase中put(), delete(), checkAndPut()这样的修改操作是独立执行的,这意味着在一个串行方式的执行中,对于每一行必须保证行级别的操作是原子性的。

region服务器提供了一个行锁(row lock)特性,这个特性保证了只有一个客户端能获取到一行数据相应的锁。在实践中,大部分客户端应用程序不会使用显式的锁,而是使用这个机制来保障每个操作的独立性。

用户应该尽量避免使用行锁,因为可能会导致死锁。在锁超时(默认是1分钟)之前,两个被阻塞的客户端会占用一个服务器的处理线程(handler),而这个线程是一种非常稀缺的资源。如果在一个频繁操作的行上发生了这种情况,那么很多其他的客户端会占用掉其所有的线程,阻塞所有其他客户端访问这台机器,导致这个region服务器将不能为其负责的region内的行提供服务。

排它锁

每一个排他锁(unique lock),无论是由服务器提供的,还是通过客户端API传入的,都能保证这一行不被其他锁锁定。换句话说,锁必须针对整个行,并且指定其行键,一旦它获得的锁定权就能防止其他的并发修改。

当一个锁被服务器端或客户端显式读取后,其他所有想要对这样数据加锁的客户端将会等待,直到当前锁被释放,或者锁的租期超时(为了确保错误的进程不会占用锁太长时间或无限期占用)。

修改行时锁定行是有意义的,但是因为历史遗留原因,Get类的一个构造器中可以显式指定锁。不过服务端根本不会用到这种方法,因为读取数据的过程中,服务器根本不需要任何锁,而是应用了一个多版本的并发控制(multiversion concurrency control-style)机制来保证行级读操作。

扫描

扫描操作的工作方式优点类似与迭代器,可以使用HTable的getScanner()方法获取扫描器。

扫描操作中,用户提供的参数不必精确匹配这两行。扫描会匹配成相等或大于给定起始行的行健。如果没有显式地指定起始行,它会从表的起始为止开始获取数据。当遇到了与设置的终止行相同或大于终止行的行健时,扫描也会停止。如果没有指定终止行健,会扫描到表尾。

扫描操作不会通过一次RPC请求返回所有匹配的行,而是以行为单位进行返回。很显然,行的数目非常大,可能有上千条甚至更多,同时在一次请求中发送大量数据,会占用大量的系统资源,并且耗费很长时间。因此Resultcan类将扫描操作转换为类似的get操作,将每一行数据封装成Result实例放入迭代器实例next中。

每一个next()调用都会为每行数据生成一个单独的RPC请求,很显然,当单元格数据较小时,这样做的性能并不好。因此使用扫描器缓存(scanner caching)可以实现一次RPC请求获取多行数据。

其中有个扫描参数叫做过滤器(filter),可直接指向Filter实例。一个打开的扫描器会占用不少服务器资源,积累多了会占用大量的对空间,因此需要确保尽早释放扫描器实例。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值