本文分析RegionServer宕机后这个region server上的region是如何在其他region server上恢复的。

region server宕机后发生了什么  

HMaster有一个RegionServerTracker对象,监控zk上/hbase/rs目录下的结点,达到监控region server下线的目的。一个region server宕机后,zk上相应结点删除,触发RegionServerTracker的nodeDeleted(),方法调用ServerManager的expireServer逻辑,对于非meta region(0.96后只有一个meta region),提交一个ServerShutdownHanlder的任务给内部线程池处理,任务的处理逻辑在handler的process()中。HBASE-7006引入了distributed log replay特性,这里以distributed log replay为例。如果开启了distributed log replay特性,那么在zk上建立一系列结点/hbase/recovering-regions/regionEncodeName/serverName,其中regionEncodeName结点内容为该region的last flush sequence id,即这个sequence id之前的所有数据都已经flush到磁盘上产生了HFile文件,这部分数据不需要进行回放。serverName结点的内容为宕机的region server上的last flushed sequence id,即所有region中最大的last flush sequence id。将宕掉server上的region assign通过round robin的方式assign其他的活着的region server,然后提交一个LogReplayHandler的任务给内部线程池,这个任务内部就是进行split log的准备工作,将hdfs上该region server的log改名,加上-splitting后缀,变成hbase.rootdir/WALs/serverName-splitting,然后进入HMaster的SplitLogManager管理范围,在zk上建立节点,路径/hbase/splitWAL/对上面改写后的log路径的encode。然后HMaster等待log被其他region server上的SplitLogWorker split完成,然后将一开始建立的一系列节点/hbase/recovering-regions/regionEncodeName/serverName删掉,然后将-splitting目录删除.

regionserver上的SplitLogWorker会不断的去监控zk上的hbase.rootdir/WALs/serverName-splitting节点,并且试图own这个节点.成功后,则给SplitLogWorker内部线程池提交一个HLogSplitterHandler任务,任务逻辑在对象splitTaskExecutor中,任务内部主要调用HLogSplitter.splitLogFile(),从而进到HLogSplitter的boolean splitLogFile(FileStatus logfile, CancelableProgressable reporter) throws IOException. 该函数内部会读-splitting目录内部的hlog文件,然后将每条log entry加入到一个sink中,sink是一个抽象类,根据是否配置使用distributed log replay,使用不同的子类,对于distributed log replay来说,使用LogReplayOutputSink,否则使用LogRecoveredEditsOutputSink。回到函数boolean splitLogFile(FileStatus logfile, CancelableProgressable reporter) throws IOException,函数的逻辑主要是从hlog中解析出一条条的log entry,如果log entry的sequence id比zk上相应的/hbase/recovering-regions/regionEncodeName 节点记录的sequence id小,那么说明这条log entry对应的内容已经持久化在HFile中,不需要进行回放,否则将这条日志append到成员EntryBuffers对象中,EntryBuffers内部会对log entry按照region进行分组,同一个Region的log entry记录在对象RegionEntryBuffer中。同时,会有一些写线程,不断的从EntryBuffers中取出RegionEntryBuffer对象,将其append到sink中,在这里,是LogReplayOutputSink。LogReplayOutputSink中积攒到一批日志,会调用WALEditsReplaySink的replayEntries()方法,通过ReplayServerCallable这个rpc发给这个region被assign后的新的region server让其回放,由于这里使用多个写线程给其他的region server发送日志,所以叫作distributed log replay。

非distributed log replay的模式下,LogRecoveredEditsOutputSink的工作是直接按照region,把相对应的log写到hdfs的 hbase.rootdir/data/namespace(比如test)/table_name/region_encoded_name/recovered.edits下。后续region被其他region server open时,会来这看是不是有需要回放的hlog.

需要注意的是,在distributed log replay模式下,region是被open后,然后才replay ,可以看到open成功后,这个region可以提供写,但是不能提供读,因为数据不全。

以上是region server宕机后,触发的HMaster和其他region server的逻辑。

下面看看region server 收到HMaster的open region指令的逻辑。

Open Region

如果是distributed log replay,那么会去zk上找 /hbase/recovering-regions/regionEncodeName/serverName,将region记录在map recoveringRegions中。然后如果不是meta region,则提交一个OpenRegionHandler任务到内部线程池中,任何的逻辑主要是open region,代码在openHRegion(final CancelableProgressable reporter),最后主要代码在initializeRegionInternals()内部调用initializeRegionStores()方法中。这个方法主要就是从hdfs中load region对应的HFile文件,并且如果region目录下的recovered.edits有hlog文件需要回放,则进行回放(方法replayRecoveredEditsIfAny)。

加载HFile过程中很重要的一点是,需要将这个HRegion下的所有的HStore(一个column family对应一个HStore,一个HStore下面有多个HFile和一个memstore)中最大的memstoreTS拿出来,加1后去初始化HRegion内部的mvcc对象,这个对象用于负责实现MVCC。这个时间戳相当于事物ID,用来判断数据是否对某事务可见。

参考资料

hbase-server-0.98.3-hadoop2.jar

https://issues.apache.org/jira/browse/HBASE-7006

http://blog.cloudera.com/blog/2012/07/hbase-log-splitting/

HBase RegionServer宕机处理恢复的更多相关文章

  1. HBase–RegionServer宕机恢复原理

    Region Server宕机总述 HBase一个很大的特色是扩展性极其友好,可以通过简单地加机器实现集群规模的线性扩展,而且机器的配置并不需要太好,通过大量廉价机器代替价格昂贵的高性能机器.但也正因 ...

  2. 如何避免regionServer宕机

    为什么regionserver 和Zookeeper的session expired? 可能的原因有 1. 网络不好. 2. Java full GC, 这会block所有的线程.如果时间比较长,也会 ...

  3. 支持宕机自动恢复触发一次性或周期性任务执行的组件包首次介绍-easyTask

    easyTask介绍 一个方便触发一次性或周期性任务执行的工具包,支持海量,高并发,高可用,宕机自动恢复任务 使用场景 需要精确到秒的某一时刻触发任务执行.比如订单交易完成24小时后如果客户未评价,则 ...

  4. 假如Kafka集群中一个broker宕机无法恢复,应该如何处理?

    假如Kafka集群中一个broker宕机无法恢复, 应该如何处理? 今天面试时遇到这个问题, 网上资料说添加新的broker, 是不会自动同步旧数据的. 笨办法 环境介绍 三个broker的集群, z ...

  5. hbase的regionserver宕机

    错误日志: regionserver.HRegionServer: Failed deleting my ephemeral node zookeeper.RecoverableZooKeeper: ...

  6. 整合phoenix4.6.0-HBase-1.0到cdh5..4.7 编译phoenix4.6源码 RegionServer 宕机

    Phoenix 集成HBase Phoenix 版本:phoenix-4.6.0-HBase-1.0 源码下载地址: http://apache.cs.uu.nl/phoenix/phoenix-4. ...

  7. 一次修改数据库物理文件造成Mysql宕机的恢复记录

    事件起始 某夜,我正在床上冥想准备入睡,忽然同事向我求救:消息内容如下: Oh My Gold 改了些配置,啥都没了!都没了!没了!了! 我仔细询问,原来是她因为某些原因将某库的物理文件夹改名后,发现 ...

  8. mysql group replication 主节点宕机恢复

    一.mysql group replication 生来就要面对两个问题: 一.主节点宕机如何恢复. 二.多数节点离线的情况下.余下节点如何继续承载业务. 在这里我们只讨论第一个问题.也就是说当主结点 ...

  9. HBase RegionServer Pause for hours 卡顿几小时 故障

    关键词:hbase jvm gc regionserver wal pause 背景: HBase 1.1.2 客户的hbase集群最近出现RegionServer宕机情况.跟踪了master和RS日 ...

随机推荐

  1. 关于 PHP 开放 enable_dl 函数利用 图片Disable_functions

    三篇引文地址: 利用PHP扩展模块突破Disable_functions执行命令 如何编写PHP扩展 php dl函数(详细解释)

  2. Android侧滑菜单和轮播图之滑动冲突

    接手一个项目,有一个问题需要修改:轮播图不能手动滑动,手动滑动轮播图只会触发侧滑菜单. 猜测:viewpager控件(轮播图)的触摸事件被SlidingMenu控件(侧滑菜单,非第三方项目,乃是上个开 ...

  3. jieba分词加入特殊字符和空格

    将原始jieba字典中的空格更改为 @@ 1.原来:雅不可攀 3 nr 2.现在:雅不可攀@@3@@nr 将自定义用户词典加入的词与词性中间的空格更改为@@ 1.原来:牵连关系 50 n 2.现在:牵 ...

  4. beego 遇到的一些问题

    1.安装 beego 出现的问题 今天在通过 go get -u github.com/astaxie/beego 安装 beego 应用时,出现下面问题: # cd .; git clone htt ...

  5. 在Linux系统安装Nodejs最简单步骤

    一.去官网下载和自己系统匹配的文件 英文网址:https://nodejs.org/en/download/ 中文网址:http://nodejs.cn/download/ 通过  uname -a ...

  6. 笔记三:python乱码深度剖析一

    一:学习内容 python编码转换 python乱码原因深入解析 二:python编码转换 1. Python内部字符串一般都是Unicode编码,代码中字符串的默认编码与代码文件本身的编码是一致的. ...

  7. form表单select的选项值选择

    html: <form action=""> <p>选择城市</p> <p> <select name="" ...

  8. 解决启动mongod 时,出现addr already in use错误

    启动mongod   root@wangyuyu-Vostro-1440:/usr/bin# ./mongod 错误提示: Sat Aug 17 09:02:02 [initandlisten] ER ...

  9. 在LaTeX中配置西夏文字体与环境

    目录 1 配置字族 2 粗体.斜体设定 3 文本编辑器的字体设定(以Sublime Text为例) 4 附录:一些字体的下载源 警告:这篇文章的部分内容需要西夏文字体才能正常显示.若您需要安装,可参考 ...

  10. [HNOI 2018]寻宝游戏

    Description 题库链接 给出 \(n\) 个 \(m\) 位的二进制数,在每一个二进制数间插入一个 & 或 | ,第 \(0\) 个数为 \(0\) , \(0,1\) 间也要插入符 ...