HBase源码分析7—行锁和MVCC
HBase中的Row Lock
HBase是一个列式数据库,不像传统的RDBMS一样会把一整行数据作为一个整体来看待。当有两个请求并发修改同一个rowkey的A、B两个列,如果没有锁的控制,可能出现两个列分别体现了两个请求的修改的情况,这种情况是不一致的。为了避免不一致情况出现,需要行锁的控制(当然也可以像pg一样纯无锁,但那不是HBase的实现方式,暂不讨论了)。
HBase的所有操作最终都是落到region server来操作的,所以锁的实现放在了 HRegion 里。主要涉及两个类: RowLock 和 RowLockContext ,其中 RowLock 是抽象类,其具体实现是 RowLockImpl 。
RowLockContext 的作用在我看来主要有两个:
- 提供了可重入能力
- 提供了具体的锁结构
1 2 3 4 5 6 7 8 9 |
class RowLockContext { private final HashedBytes row; final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(true); final AtomicBoolean usable = new AtomicBoolean(true); // cleanup 之后被设为false final AtomicInteger count = new AtomicInteger(0); // 重入多少次 final Object lock = new Object(); // 一个用于自己synchronized的符号 private String threadName; ... } |
RowLockContext 类主要提供了两个方法: newReadLock 和 newWriteLock ,他们的实现类似这样
1 2 3 4 |
RowLockImpl newReadLock() { Lock l = readWriteLock.readLock(); return getRowLock(l); } |
getRowLock 方法用自己的 l 作为参数构造了一个 RowLock 吐出来。
1 2 3 4 5 6 7 8 9 10 |
public static class RowLockImpl implements RowLock { private final RowLockContext context; private final Lock lock; public RowLockImpl(RowLockContext context, Lock lock) { |