HBase Log Splitting(日志拆分)

该文主要介绍了HBase在一个region server崩溃后,如何通过日志拆分(Log Split)的方式来恢复丢失的修改,防止数据丢失的。

Log Split(日志拆分)

HBase为了提高写的性能,将数据的修改先放到memstore内存中,这样做的缺陷是当某个region server崩溃时,其memstore中的所有修改将会丢失,因为它们还没有被刷写到磁盘上。为了防止这情况造成的数据丢失,HBase的做法是在修改写入memstore之前,先将其写入一个称为"预写日志"(write-ahead-log,WAL)文件中。这样在遇到一个region server崩溃后,可以通过回放(replay)WAL文件重新生成memstore中丢失的修改。

由于一个region server上会有多个region,并且这些region共享一个WAL文件。WAL文件中的每个修改(也叫做edit)都包含其属于哪一个region的信息。当打开一个region时,将会replay这个region在WAL中的所有edits记录,来重新生成数据。所以,在WAL文件中的所有edit都必须按region分组形成特定的集合,通过replay这些集合来对特定的region重新生成数据。像这样在WAL文件中对edit 按region分组的过程就称为Log Split。

日志拆分(Log Split)发生在集群启动时(由HMaster负责完成)或是在region server崩溃时(由ServerShutdownHandler负责完成),因为HBase需要保持一致性。在日志拆分时,受影响的region将不可用,直到拆分完成,数据完全重置。
下图为日志拆分的过程:

HBase Log Splitting(日志拆分)_第1张图片

在开始拆分日志时,会重命名日志目录:/hbase/.logs/,,-splitting,例如:/hbase/.logs/srv.example.com,60020,1254173957298-splitting

之所以重命名日志目录,主要是为了防止region server误写入。因为可能出现region server还在正常运行,但master已经认为它已经关闭了的情况,比如region server 长时间没有响应,造成ZooKeeper没有收到其心跳,这种情况,HMaster会将该region server标识为已失败。通过重命名日志目录,任何可用的WAL文件仍然被使用,但不会发生误写入的情况。

每个日志文件每次只能拆分一个edit记录。日志拆分器每次仅读取日志文件的中一个edit记录,然后把每一个edit记录放入相应region的缓冲区里,同时日志拆分器启动若干个writer 线程,将缓冲区中的edit记录写到临时的edit恢复文件中。临时edit文件的路径如下形式:
/hbase///recovered.edits/.temp

这个临时edit文件用来保存该region在WAL文件中的所有edit记录。一旦拆分结束后,这个临时文件将被重命名为如下的形式:

/hbase///recovered.edits/

上面的sequenceid表示写入文件的第一条日志记录的序列ID。HBase就是根据sequence ID来确定是否所有的edit都已经写入。通过比较HFile中最后一条edit的sequence ID和该文件的sequenceid,如果前者大于或等于后者,则说明已经完全写入。

当日志拆分结束,每一个受影响的region都会被分配到相应的region server上。当region是打开时,将会检查recovered.edits目录下是否有edit恢复文件,如果有,将会回放这些文件,读取文件中的edit记录并保存到memstore中。在所有的edit文件回放之后,将memstore中的内容刷写到磁盘上(HFile),然后删除这些edit文件。

在HBase 0.92版本之前,是在HMaster上通过一个线程按顺序完成日志拆分的整个过程的,但这比较耗时。从0.92版本引入了分布式的日志拆分,拆分的工作有master转移到了额region服务器上,大大降低了拆分的时间。

最新的分布式模式是通过ZooKeeper将每一个被丢弃的日志文件分发给一个region server。这些region server 检测ZooKeeper是否有可处理的日志文件,它们将通过竞争,获胜的region server启动一个线程来读取并拆分这个日志文件。

你可能感兴趣的:(hbase)