HBase行级事务锁

CodeHor
• 阅读 2703

写写并发控制:

只需要在写入(或更新)之前先获取行锁,如果获取不到,说明已经有其他线程拿了该锁,就需要不断重试等待或者自旋等待,直至其他线程释放该锁。拿到锁之后开始写入数据,写入完成之后释放行锁即可。这种行锁机制是实现写写并发控制最常用的手段,后面可以看到MySQL也是使用行锁来实现写写并发的。

批量写入多行的写写并发:

HBase支持批量写入(或批量更新),即一个线程同时更新同一个Region中的多行记录。那如何保证当前事务中的批量写入与其他事务中的批量写入的并发控制呢?思路还是一样的,使用行锁。但这里需要注意的是必须使用两阶段锁协议,即:

(1) 获取所有待写入(更新)行记录的行锁

(2) 开始执行写入(更新)操作

(3) 写入完成之后再统一释放所有行记录的行锁

不能更新一行锁定(释放)一行,多个事务之间容易形成死锁。两阶段锁协议就是为了避免死锁,MySQL事务写写并发控制同样使用两阶段锁协议。

Rowkey info:company info:role
greg cloudera engineer

Rowkey info:company info:role
greg restaurant waiter

两个并发写入请求同时进来,分别对一行数据进行写入。若没有并发控制,会出现交叉情况。

Rowkey info:company info:role
greg restaurant engineer

读写并发控制:
事务A完成。
Rowkey info:company info:role
greg cloudera engineer

开始执行事务B
Rowkey info:company
greg restaurant

此时来了读请求,info:role还未更新完成。

info:role
waiter

读取到的数据为:
Rowkey info:company info:role
greg restaurant engineer

出现数据不一致的情况。

多版本并发控制(MVCC机制-Mutil Version Concurrent Control):

两个写事务分别分配了序列号1和序列号2,读请求进来的时候事务1已经完成,事务2还未完成,因此分配事务1对应的序列号1给读请求。此时序列号1对本次读可见,序列号2对本次读不可见。

+---+---+---+---+---+---+---+---+---+----+----+----+----+  
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |  
+---+---+---+---+---+---+---+---+---+----+----+----+----+
    

所有事务都会生成一个region级别的自增序列。

1、如果事务1和事务2和事务3是操作的同一行,事务1完成,事务2未完成,事务3完成。此时读请求过来读取该行,只能读取到事务1.当事务2完成后才能读取到事务3

2、如果事务1~事务12操作的不同行,事务1~事务11都未完成,事务12完成,此时读请求过来读取事务12的数据,仍旧会等待事务1~事务11完成后才能读取事务12的内容,
所以此时读取到的是事务12对应行的之前的事务内容。因为目前还未做到对未完成的事务与当前读请求的内容比较的功能,而且一个事务中可能包含多行。若要与当前请求比较,
会比较耗性能。

点赞
收藏
评论区
推荐文章
Wesley13 Wesley13
3年前
java 面试知识点笔记(十一)多线程与并发
自适应自旋锁:(java6引入,jvm对锁的预测会越来越精准,jvm也会越来越聪明)1.自选次数不再固定2.由前一次在同一个锁上的自旋时间及锁拥有者的状态来决定(如果在同一个锁对象上自旋等待刚刚成功获取过锁并且持有锁的线程正在运行中,jvm会认为该锁自旋获取到锁的可能性很大,会自动增加等待时间,相反jvm如果可能性很小会省掉自旋过程,
Wesley13 Wesley13
3年前
java中的锁
记录一下公平锁,非公平锁,可重入锁(递归锁),读写锁,自旋锁的概念,以及一些和锁有关的java类。公平锁与非公平锁:公平锁就是在多线程环境下,每个线程在获取锁时,先查看这个锁维护的队列,如果队列为空或者自身就是等待队列的第一个,就占有锁。否则就加入到等待队列中,按照FIFO的顺序依次占有锁。非公平锁会一上来就试图占
Easter79 Easter79
3年前
synchronized在jdk1.6之后引入的一些优化方案
自旋锁    jdk1.6之后默认开启,可以使用参数XX:UseSpinning控制,自旋等待不能代替阻塞,且先不说对处理器数量的要求,自旋等待本身虽然避免了线程切换的开销,但它是要占用处理器时间的,因此,如果锁被占用的时间很短,自旋等待的效果就会非常好,反之,如果锁被占用的时候很长,那么自旋的线程只会白白消耗处理器资源,而不会做任何有用的工
Wesley13 Wesley13
3年前
MySQL 中的共享锁和排他锁的用法
在MySQL中的行级锁、表级锁和页级锁中,咱们介绍过,行级锁是MySQL中锁定粒度最细的一种锁,行级锁能大大减少数据库操作的冲突。行级锁分为共享锁和排他锁两种,本文将详细介绍共享锁和排他锁的概念、使用方式及注意事项。共享锁(ShareLock)共享锁又称读锁,是读取操作创建的锁。其他用户可以并发读取数据,但任
Wesley13 Wesley13
3年前
MySQL中的共享锁与排他锁
在MySQL中的行级锁,表级锁,页级锁(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fwww.hollischuang.com%2Farchives%2F914)中介绍过,行级锁是Mysql中锁定粒度最细的一种锁,行级锁能大大减少数据库操作的冲突。行级锁分为共享锁和排他锁两种,本文将详细
Stella981 Stella981
3年前
Python的锁
互斥锁锁通常被用来实现对共享资源的同步访问。为每一个共享资源创建一个Lock对象,lLock()创建一个锁,初始状态是未锁定当你需要访问该资源时,调用l.acquire方法来获取锁对象(如果其它线程已经获得了该锁,则当前线程需等待其被释放),待资源访问完后,再调用l.release方法释放锁!(https:
Wesley13 Wesley13
3年前
MySQL锁
<br1\.表锁表锁分为写锁,读锁,二者读读不阻塞,读写阻塞,写写阻塞<br<br2\.行锁行锁分为共享锁,排他锁,即读锁和写锁多粒度锁机制自动实现表、行锁共存,InnoDB内部有意向表锁意向共享锁(IS):事务在给一个数据行加共享锁前必须先取得该表的IS锁。
Wesley13 Wesley13
3年前
Mysql锁总结
今天我们来介绍一下Mysql中不同类型的锁数据库锁设计的初衷是处理并发问题。作为多用户共享的资源,当出现并发访问的时候,数据库需要合理地控制资源的访问规则。而锁就是用来实现这些访问规则的重要数据结构根据加锁的范围,MySQL里面的锁大致可以分成全局锁、表级锁和行锁三类全局锁全局锁就是对整个数据库实例加锁。MySQL提供了一个加全
Wesley13 Wesley13
3年前
Java并发编程:Lock
一.synchronized的缺陷synchronized是java中的一个关键字,也就是说是Java语言内置的特性。那么为什么会出现Lock呢?  在上面一篇文章中,我们了解到如果一个代码块被synchronized修饰了,当一个线程获取了对应的锁,并执行该代码块时,其他线程便只能一直等待,等待获取锁的线程释放锁
Wesley13 Wesley13
3年前
Java多线程锁释放
Java多线程运行环境中,在哪些情况下会使对象锁释放?由于等待一个锁的线程只有在获得这把锁之后,才能恢复运行,所以让持有锁的线程在不再需要锁的时候及时释放锁是很重要的。在以下情况下,持有锁的线程会释放锁:(1)执行完同步代码块,就会释放锁。(synchronized)(2)在执行同步代码块的过程中,遇到异常而导致线程终止,锁也会被释放。(exc
Wesley13 Wesley13
3年前
JDK里的自旋锁
自旋锁是采用让当前线程不停地的在循环体内执行实现的,当循环的条件被其他线程改变时才能进入临界区。JDK里面自旋锁的实现有SynchronousQueue 和LinkedTransferQueue。 本文只是自己对源码的简单理解。先说公平锁,先等待的线程先获得数据。SynchronousQueue的内部类TransferQueue实现了公平锁。