HBase WAL - tenji/ks GitHub Wiki

HBase Write-Ahead-Log

HBase 的 Write Ahead Log (WAL) 提供了一种高并发、持久化的日志保存与回放机制。每一个业务数据的写入操作(PUT / DELETE)执行前,都会记账在 WAL 中。

WAL 最重要的作用是灾难恢复。和 MySQL 的 Binlog 类似,它记录所有的数据改动。一旦服务器崩溃,通过重放 log,我们可以恢复崩溃之前的数据。这也意味如果写入 WAL 失败,整个操作将认为失败。

我们先看看 HBase 是如何做到的。首先,客户端初始化一个可能对数据改动的操作,如put(Put), delete(Delete)incrementColumnValue()。这些操作都将被封装在一个 KeyValue 对象实例中,通过RPC 调用发送给 HRegionServer (最好是批量操作)。 一旦达到一定大小,HRegionServer 将其发送给 HRegion。这个过程中,数据会首先会被写入 WAL,之后将被写到实际存放数据的 MemStore 中。

当 MemStore 到达一定大小,或者经过一段时间后,数据将被异步地写入文件系统中。然而,在两次写入文件系统之间的数据,是保留在内存中的。如果这个时候系统崩溃,那数据会丢失吗?别急,我们有WAL!

一、WAL 几个重要的类

1.1 HLog

...

1.2 HLogKey

...

1.3 LogFlusher

...

1.4 LogRoller

...

1.5 Replay

...

二、Log Split(日志拆分)

HMaster 启动时会启动 SplitLogManager, 并进行 Log 分割。那么什么是 Log Split, 为什么要进行 log split 呢?要回答这个问题,我们先来看一下 HLog (也叫 WAL)的格式,如下图:

HLog 是每个 Region server 只有一份,一个 region server 上的所有 region 共用一个 Hlog, hlog 用来在系统异常 down 掉,MemStore 中大量更新丢失时,对数据进行恢复。从上图中可以看出,对每个 region 的更新在 hlog 里不是连续的,而是分散在 Hlog 里的。Hlog 中的每项更新都会记录该更新所属的 region, HBase 要通过在每个 region 上应用 hlog 中的更新来恢复数据,因此需要把 hlog 中的更新按照 region 分组,这一把 hlog 中更新日志分组的过程就称为 log split(日志分割)。

对于 HBase 0.90 及之前的版本, log split 都是由 master 完成的, master 启动时,所有的 log 由 master 顺序进行分割,如果 log 文件很多很大,这一过程在 master 上是很耗时的,但是同时所有的 region server 都在闲着,等待 master 完成 log split。 HBase 0.92 版本开始采用了分布式日志分割技术(HBase-1364)。对于分布式日志分割,master 负责将日志分割的任务分配给不同的 region server,有 region server 同时并行完成日志分割,大大提升了日志分割速度。

HMaster 启动时会启动 SplitLogManager,该类负责把 log split 任务通过创建 znode 发布到 ZooKeeper 上,并监控 znode 了解 log split 任务完成状态。在每个 region server 中有单独的线程监控 ZooKeeper 中 log split 相关的 znode, 一旦发现自己的任务,就开始进行 log split, 最终负责 log split 实际工作的类是 HLogSplitter。

分布式日志分割可以通过配置项hbase.master.distributed.log.splitting来控制,默认为true, 即默认情况下分布式日志分割是打开的。

参考链接