HBase行锁和扫描

Posted 法海你懂不

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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实例。一个打开的扫描器会占用不少服务器资源,积累多了会占用大量的对空间,因此需要确保尽早释放扫描器实例。

以上是关于HBase行锁和扫描的主要内容,如果未能解决你的问题,请参考以下文章

MySQL表锁和行锁详解

149期MySQL行锁和表锁的含义及区别是什么?

MySQL 表锁和行锁 问题

SQL 行锁和事务

mysql中InnoDB存储引擎的行锁和表锁

RR隔离级别下锁情况(探究gap锁和行锁)