HBase不同版本中对WAL日志的处理
共 973字,需浏览 2分钟
·
2023-06-23 00:24
我们知道,HBase在处理写流程(put操作)时,RegionServer会先将数据Append到WAL日志中,在写入MemStore,这时就返回客户端通知成功了。但是,在不同的版本中(HBase 1.6和Hbase 2.x),处理WAL的具体逻辑有很大区别。因此,网络中不同的文章可能会让读者感到迷惑,我们不妨从源码中一探究竟。
HBase 2.3.2的流程:
1、对要操作的数据添加行锁(List(RowKey)),并添加读锁(这个锁是HRegion类里的可重入读写锁)
2、对数据更新timestamp字段(如果提交put请求的数据没有指定timestamp,HBase客户端会给一个Long.MAX_VALUE作为时间戳的值,RegionServer也会根据这个值判断是否对时间戳更新)
3、Append the WALEdits to WAL and sync。将WALEdits追加到WAL日志,并进行同步。其中append和同步是一个生产消费模型,append是生产者,将数据写入RingBuffer中,RingBuffer是一个线程安全的消息队列。
数据append成功后,会有一个txid,然后执行sync()。
其中sync也有对应的不同策略,主要的策略有默认(sync)、aync、fsync等,其中的区别可以参考linux关于IO同步的策略。
4、写入MemStore
5、完成操作。主要是执行
可以看到,region内部是有mvcc的,也就是说当数据写入WAL后,或者写入MemStore后,数据依然无法被读,只有执行完这一步才能被客户端读到。
6、由于上一步是执行的completeAndWait,也就是说这是一个异步操作,因此在finally里会再次执行
然后会释放锁,并向客户端返回。
从这个流程看来,只要数据成功写入WAL,数据就有保证,但是对于HBase 1.6版本可不是这样。
在HBase 1.6版本中,其中的第3步,仅执行append,并不会执行sync,当数据写入MemStore后,会执行sync,如果sync失败,会对memstore进行回滚。
这里syncOrDefer方法已经很明显了,如果同步异常会抛出异常,而主方法中会捕获异常,并对一个布尔变量进行判断,进而对MemStore回滚。