本文翻译自: http://www.larsgeorge.com/2010/01/hbase-architecture-101-write-ahead-log.html
什么是Write-ahead-Log呢?在之前的博文中已经讲过了HBase的基本存储架构。其中提到的一个部分就是Write-ahead-Log,或者简称WAL。这边博文将详细的讲述hlog的工作流程。
WAL是故障发生时进行恢复的重要工具。这和MYSQL中的BIN log很相似,都是记录所有的数据操作。这种策略是非常重要的以防内存发生一些异常,这可以使服务器发生故障的时候根据log恢复到他发生刚故障之前的那个时刻。这也意味着数据写入的时候如果WAL写入失败了,这次数据操作也会被判定为失败的。
让我们在高级视图上看一下HBase是怎么实现这个功能的。首先客户端初始化一个更改数据的动作,这现在被叫 put(Put),delete(Delete) 和 incrementColumnvalue()(这里有是也简称为incr),每一种改动都被包装进KeyValue对象利用远程调用发送到Reginoserver对应这次改动的Region(s)中,数据在RegionServer中首先被写入WAL,然后被写入MemStore。
最后当Memstore达到一定的大小或者到达指定的时刻之后,数据被异步的持久化到文件系统上。在这之前数据是存储在内存中的,在这段时间里面如果regionserver崩溃了,内存的数据就没有了,但是我们有WAL,就可以恢复数据。
HLog

LogFlusher
LogRoller
另外一个控制log滚动的参数是hbase.regionserver.hlog.blocksize 和 hbase.regionserver.logroll.mutilplier,默认设置是达到SequenceFile的blocksize的95%的时候对日志进行滚动,一般这个大小是64M,所以要么是logs达到一定的大小,要么是logs经历了一定的时间,他才会被滚动。
Replay
这些老的日志通常是由前一个region server崩溃留下的,当master发现有region server崩溃的时候,它会将这个regionserver的日志根据所属的region进行拆分,然后放到各自Region的目录下面,然后上面提到的重放机制会检测到日志进行恢复。值得注意的是只有被拆分的log才能被恢复,拆分日志使用的是HLog.splitLog()。老的log会被读入内存然后被写入各自所属的region。
Issues
用BigTable里面的话来说就是这会造成大量的磁盘寻址。
HBase遵循的规则类似,就像上面解释的那样,这会滚动出很多的日志直到数据操作被写入文件系统,这样这些log就会被删除,如果想单独的每个region都分开写log文件,迟早会造成一些问题。
目前为止看起来是没有问题,但是重申一次,它会在事情变糟糕的时候发生问题。在平常,将所有的数据改动都安全的持久化到文件系统,这很好。但是如果在region server崩溃的时候需要分割日志文件,但是这时候日志文件是存储在各个region下的,这里也并没有索引能够找到这些日志文件,所以这时候master无法找到日志文件。
另外一个问题就是数据安全。你想依赖这个系统在不管什么新奇的场景下来保全你的数据。如果想要尽量的使数据的安全性高你可以把log flush的时间调整得尽量的低。当数据流被写入到这个系统之后,是否它已经被写入到磁盘了呢。
到了这个时候我们已经非常的清楚HLog就是用来保证数据的安全性的了。因此一个log应该要保持打开长达一个小时(甚至更长如果有这样的配置)。当数据到达的时候一个新的key/value被写入Sequence File然后被flush到磁盘。但是这并不是Hadoop的工作方式。它提供了一个API,这个API可以打开一个文件,写入大量的数据,然后马上关闭,然后留下一个不变的文件留给其他人访问。而且只有文件被关闭的时候他对其他人才是可见并且可读的。如果一个进程在写入数据的死掉了,这次的操作会被认定是失败的。还有一个需求就是允许能够读到server在崩溃那个时刻的log或者说越近越好。
append在HDFS中通常很有用但是在HBase中却不是,HBase中使用hflush().他所做的是将一起的数据写入磁盘当log被写入的时候,这是为了使server崩溃之后我们可以安全的读到崩溃的最后一刻的数据。
Append/Sync
Distributed Log Splitting
剩下的问题就是如何split log更快了。下面是BigTable在论文里面提出的解决的方案:
为了不重复的读取log,首先将提交的log进行排序,按照(table,row name,long seq number) ,这样就可以按顺序读出记录分配到各个server上去。
https://blog.csdn.net/u010916254/article/details/48025445