hbase hlog

   Hbase 每一次对数据的修改都会写入到memorystore 中,写入成功后,Hbase 便会将这条记录写入到hlog中去。当memorystore满足一定的条件后,hregionserver 便会将memorystore flush到磁盘中,记录着这些memorystore的hlog便会被删除掉。当hbase regionserver正常运行时,hlog并不起到任何作用,但是当regionserver出现故障宕机时,未刷写到磁盘中的memorystore数据便会丢失,此时便可以通过hlog对丢失的数据进行数据恢复。hlog恢复数据的过程被称为log split。本文阐述了hlog的基本结构、生成过程以及log split 的方式。

一、hlog的基本结构

hlog是regionserver级别的,hlog由regionserver中的region共享,其分布如下图所示:


hlog 由一个个entry构成,HLogKey由sequenId、wirte time 、cluster ids、region name、table name 构成

二、hlog 生成过程


hlog 滚动:regionserver启动一个线程定期(由参数’hbase.regionserver.logroll.period’决定,默认1小时)对hlog进行滚动,重新创建一个新的hlog.,这样,regionserver上就会产生很多小的hlog 文件,hbase这样做的原因是当hbase的数据越来越多时,hlog的大小就会越来越大。当memorystore 刷写到磁盘时,过期的hlog 并没有作用便可删除,一个个小的hlog文件便于删除。

hlog失效:当memorystore flush 到磁盘后,将hlog中最大的seqId与memorystore中最大的seqId进行比较,如果小于memorystore中的seqId,则改hlog失效,便将该hlog移到由wals文件夹移到oldwals文件中去

hlog删除:当hlog失效后,不立即删除是因为region replica可能正在对hlog进行读写,所以regionserver启动一个线程每隔一段时间(由参数’hbase.master.cleaner.interval’,默认1分钟)对检查该hlog是否可以被删除,在oldwals文件夹中的hlog文件都有过期时间,默认(由参数’hbase.master.logcleaner.ttl’决定)为10分钟

三、log split过程

HBase的故障恢复我们都以RegionServer宕机恢复为例,引起RegionServer宕机的原因各种各样,有因为Full GC导致、网络异常导致、官方Bug导致(close wait端口未关闭)以及DataNode异常导致等等。

这些场景下一旦RegionServer发生宕机,HBase都会马上检测到这种宕机,并且在检测到宕机之后会将宕机RegionServer上的所有Region重新分配到集群中其他正常RegionServer上去,再根据HLog进行丢失数据恢复,恢复完成之后就可以对外提供服务,整个过程都是自动完成的,并不需要人工介入。基本原理如下图所示:


log split有三种方式,分别是 log split 、distributed log split 、distributed log repay

1.log split


log split过程是由Hmaster控制完成的,流程如下

1.将hdfs 上对应regionserver的hlog目录重命名(regionserver hlog文件一般存放在/hbase/wals/regionserver/目录中)为/hbase/wals/regionserver-spliting,为了防止hmaster在进行log split时客户端还对regionserver进行读写请求

2.Hmaster 读取hlog文件,并按region进行分组,对每个region生成一个buffer,并将hlog文件数据读取到各个region中去。

3. 每个buffer会对应启动一个写线程,负责将buffer中的数据写入hdfs中(对应的路径为/hbase/table_name/region/recoverd.edits/.tmp),再等Region重新分配到其他RegionServer之后按顺序回放对应Region的日志数据。

这种日志切分可以完成最基本的任务,但是效率极差,在某些场景下(集群整体宕机)进行恢复可能需要N个小时!也因为恢复效率太差,所以开发了Distributed Log Splitting架构。

2.distributed log split

distributed log split 是 log split的分布式实现,由hmater和regionserver共同完成,hmaster作为协调者,regionserver为log split的实际工作者,如图所示:


Distributed Log Splitting

Distributed Log Splitting是Log Splitting的分布式实现,它借助Master和所有RegionServer的计算能力进行日志切分,其中Master作为协调者,RegionServer作为实际的工作者。基本工作原理如下图所示:

1. Master会将待切分日志路径发布到Zookeeper节点上(/hbase/splitWAL),每个日志作为一个任务,每个任务都会有对应状态,起始状态为TASK_UNASSIGNED

2. 所有RegionServer启动之后都注册在这个节点上等待新任务,一旦Master发布任务之后,RegionServer就会抢占该任务

3. 抢占任务实际上首先去查看任务状态,如果是TASK_UNASSIGNED状态,说明当前没有人占有,此时就去修改该节点状态为TASK_OWNED。如果修改失败,说明其他RegionServer也在抢占,修改成功表明任务抢占成功。

4. RegionServer抢占任务成功之后会分发给相应线程处理,如果处理成功,会将该任务对应zk节点状态修改为TASK_DONE,一旦失败会修改为TASK_ERR

5. Master会一直监听在该ZK节点上,一旦发生状态修改就会得到通知。任务状态变更为TASK_ERR的话,Master会重新发布该任务,而变更为TASK_DONE的话,Master会将对应的节点删除

下图是RegionServer抢占任务以及抢占任务之后的工作流程:

1. 假设Master当前发布了4个任务,即当前需要回放4个日志文件,分别为hlog1、hlog2、hlog3和hlog4

2. RegionServer1抢占到了hlog1和hlog2日志,RegionServer2抢占到了hlog3日志,RegionServer3抢占到了hlog4日志

3. 以RegionServer1为例,其抢占到hlog1和hlog2日志之后会分别分发给两个HLogSplitter线程进行处理,HLogSplitter负责对日志文件执行具体的切分,切分思路还是首先读出日志中每一个数据对,根据HLogKey所属Region写入不同的Region Buffer

4. 每个Region Buffer都会有一个对应的写线程,将buffer中的日志数据写入hdfs中,写入路径为/hbase/table/region2/seqenceid.temp,其中seqenceid是一个日志中某个region对应的最大sequenceid

5. 针对某一region回放日志只需要将该region对应的所有文件按照sequenceid由小到大依次进行回放即可

这种Distributed Log Splitting方式可以很大程度上加快整个故障恢复的进程,正常故障恢复时间可以降低到分钟级别。然而,这种方式会产生很多日志小文件,产生的文件数将会是M * N,其中M是待切分的总hlog数量,N是一个宕机RegionServer上的Region个数。假如一个RegionServer上有200个Region,并且有90个hlog日志,一旦该RegionServer宕机,那这种方式的恢复过程将会创建 90 * 200 = 18000个小文件。这还只是一个RegionServer宕机的情况,如果是整个集群宕机小文件将会更多!!!

转载自:https://blog.csdn.net/lw_ghy/article/details/60779289

你可能感兴趣的:(hbase hlog)