Hbase-0.98.6源码分析--行锁
2016-06-21 11:25
393 查看
在传统的关系型数据库,如MySQL中,存在事务(Transaction)这一概念 ,事务是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。 事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会执行。通过将一组相关操作组合为一个要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠。一个逻辑工作单元要成为事务,必须满足ACID(原子性、一致性、隔离性和持久性)属性。
在事务特性方面,HBase这种NoSQL数据库中,并没有事务这种概念,它为了保证操作的原子性,采用行锁机制。HBase只支持单row的事务,不能保证跨row(cross-row)的事务。HBase通过行锁来实现单row事务。客户端进行操作时,可以显式对某一个行加锁,但官方并不推荐,原因是两个客户端很可能在拥有对方请求的锁时,又同时请求对方已拥有的锁,这样便形成了死锁,在锁超时前,两个被阻塞的客户端都会占用一个服务端的处理线程,而服务器线程是非常稀缺的资源。hbase在内部会默认的加行锁。在行锁未释放该行前,最起码其他访问者是无法对该行做修改的,即要修改的话,必须得获得该行的锁才能拥有修改改行数据的权限。
HBase行锁是利用Java并发包concurrent里的CountDownLatch(1)来实现的。它的主要思想就是在服务器端每个访问者单独一个数据处理线程,每个处理线程针对特定行数据修改时必须获得该行的行锁,而其他客户端线程想要修改数据的话,必须等待前面的线程释放锁后才被允许,这就利用了Java并发包中的CountDownLatch,CountDownLatch为Java中的一个同步辅助类,在完成一组正在其他线程中进行的操作之前,它允许一个或多个线程一直等待。这里,将线程数设置为1,十分巧妙的实现了独占锁的概念。
HBase的行锁主要是通过HRegion的两个内部类实现的,其中一个是RowLock,另外一个是RowLockContext。首先看RowLock这个类,其定义如下:
再看RowLockContext的源码:
通过源码,我们能清晰地看到,RowLockContext利用了java的concurrent并发包里的CountDownLatch(1)实现了线程对对象的独占锁。
新加锁时,通过调用newLock()方法即可实现,首先锁的计数器lockCount加1,然后返回由当前RowContext构造RowLock实例即可。
释放锁时,通过调用releaseLock()方法即可实现,首先通过ownedByCurrentThread()方法确保调用releaseLock()方法的当前线程是否和RowContext持有的线程一致,然后,锁的计数器lockCount减1,并且,如果lockCount为0的话,说明不再有操作占用该行,将row对应的行锁从数据结构lockedRows中删除,允许其他线程获得该行的行锁,最后,最重要的一步,latch.countDown(),就可完成行锁的释放了。
至于行锁在HBase中的具体应用,举一个之前讲到过的方法doMiniBatchMutation()方法,在《Hbase-0.98.6源码分析--Put写操作HRegionServer端流程》中讲到过。该方法就调用了行锁机制。
在对一行数据操作之前,都会调用getRowLock()方法,获得该行数据的行锁。代码如下:
在事务特性方面,HBase这种NoSQL数据库中,并没有事务这种概念,它为了保证操作的原子性,采用行锁机制。HBase只支持单row的事务,不能保证跨row(cross-row)的事务。HBase通过行锁来实现单row事务。客户端进行操作时,可以显式对某一个行加锁,但官方并不推荐,原因是两个客户端很可能在拥有对方请求的锁时,又同时请求对方已拥有的锁,这样便形成了死锁,在锁超时前,两个被阻塞的客户端都会占用一个服务端的处理线程,而服务器线程是非常稀缺的资源。hbase在内部会默认的加行锁。在行锁未释放该行前,最起码其他访问者是无法对该行做修改的,即要修改的话,必须得获得该行的锁才能拥有修改改行数据的权限。
HBase行锁是利用Java并发包concurrent里的CountDownLatch(1)来实现的。它的主要思想就是在服务器端每个访问者单独一个数据处理线程,每个处理线程针对特定行数据修改时必须获得该行的行锁,而其他客户端线程想要修改数据的话,必须等待前面的线程释放锁后才被允许,这就利用了Java并发包中的CountDownLatch,CountDownLatch为Java中的一个同步辅助类,在完成一组正在其他线程中进行的操作之前,它允许一个或多个线程一直等待。这里,将线程数设置为1,十分巧妙的实现了独占锁的概念。
HBase的行锁主要是通过HRegion的两个内部类实现的,其中一个是RowLock,另外一个是RowLockContext。首先看RowLock这个类,其定义如下:
再看RowLockContext的源码:
通过源码,我们能清晰地看到,RowLockContext利用了java的concurrent并发包里的CountDownLatch(1)实现了线程对对象的独占锁。
新加锁时,通过调用newLock()方法即可实现,首先锁的计数器lockCount加1,然后返回由当前RowContext构造RowLock实例即可。
释放锁时,通过调用releaseLock()方法即可实现,首先通过ownedByCurrentThread()方法确保调用releaseLock()方法的当前线程是否和RowContext持有的线程一致,然后,锁的计数器lockCount减1,并且,如果lockCount为0的话,说明不再有操作占用该行,将row对应的行锁从数据结构lockedRows中删除,允许其他线程获得该行的行锁,最后,最重要的一步,latch.countDown(),就可完成行锁的释放了。
至于行锁在HBase中的具体应用,举一个之前讲到过的方法doMiniBatchMutation()方法,在《Hbase-0.98.6源码分析--Put写操作HRegionServer端流程》中讲到过。该方法就调用了行锁机制。
在对一行数据操作之前,都会调用getRowLock()方法,获得该行数据的行锁。代码如下:
相关文章推荐
- linux 下 pip 安装教程
- 通过SQLyog远程管理linux下mysql过程中遇到的问题以及解决方法
- java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
- MemoryAnalyzer MAT介绍
- 互联网协议入门
- 第十七周 6.20 --- 6.26
- java 服务器学习之 位运算
- 8-27练习
- C++ fstream流的eof()函数多读一行的问题
- EventBus3.0.0了解及使用
- Lua笔记 & 与C之间的交互
- 第6章 构建可启动的系统镜像
- [leetcode] 【查找】 35. Search Insert Position
- 二分法查找
- 源程序出现各种奇怪的符号P
- 5种方法快速去掉HTML中Inline-Block的空白
- JSP和JS的区别
- android:clearTaskOnLaunch=true 和android:finishTaskOnLaunch=true
- Tomcat 系统架构与设计模式,第 1 部分: 工作原理
- C++网络编程服务器select模型(参考)