从源码看HBase的写入流程
最近在看HBase,琢磨了一下HBase的写入流程,我的测试环境安装的HBase版本是2.1.0-cdh6.3.2,那么直接在IDEA配置好POM文件,下载对应版本的Jar包和文档,找到org.apache.hadoop.hbase.regionserver.HRegion.java
,开撕源码。
可以找到源码中关于这部分的注释比较清晰明了:
STEP 1. Try to acquire as many locks as we can and build mini-batch of operations with
locked rows
STEP 2. Update mini batch of all operations in progress with LATEST_TIMESTAMP timestamp
We should record the timestamp only after we have acquired the rowLock,
otherwise, newer puts/deletes are not guaranteed to have a newer timestamp
STEP 3. Build WAL edit
STEP 4. Append the WALEdits to WAL and SYNC.
STEP 5. Write back to memStore
STEP 6. Complete MiniBatchOperations: If required calls postBatchMutate() CP hook and
complete mvcc for last writeEntry
STEP 7. Apply to memstore
首先HBase首先获取一些锁,在导入的包中,可以发现import java.util.concurrent.locks.Lock;
不难看出这里的获取的锁是JUC的锁。
然后构建mini-batch
,并使用最后的时间戳来更新mini-batch;
把操作追加到WAL并且同步。
再写入menStore,写入成功以后才在Finally中释放锁。
Hbase2.1.0版本与1.3.1版本相比,有了不少的改进:
- 加入了mini-batch,每次更新是针对小批量的操作,提高了整体的吞吐率;
- WAL的同步时机不同,在1.3.1版本中是先写入WALedits,再写入memStore,最后才对WAL进行同步,在2.1.0版本中的顺序变成了先写WAL并同步,然后再写memStore。在2.1.0的顺序更加符合我们的逻辑,理解起来也更简单。
总结一下HBase的写入逻辑:
- Client先访问zookeeper,获取hbase:meta表位于哪个Region Server。
- 访问对应的Region Server,获取hbase:meta表,根据读请求的namespace:table/rowkey,查询出目标数据位于哪个Region Server中的哪个Region中。并将该table的region信息以及meta表的位置信息缓存在客户端的meta cache,方便下次访问。
- 与目标Region Server进行通讯;
- 将数据顺序追加到WAL;
- 将数据写入对应的MemStore,数据会在MemStore进行排序;
- 向客户端发送ack;
- 等达到MemStore的刷写时机后,将数据刷写到HFile。
看过源码之后,对于HBase的写入有了更深入的认识。