searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

HBase RIT机制

2023-09-04 06:07:28
45
0

HBase RIT机制,全称为Region in Transition,意指Region变迁机制,实际上是指在一次特定操作行为中Region状态的变迁。

Region状态介绍

HBase在RegionState类中定义了Region的主要状态,如下图所示。

上图中实际上定义了四种会触发Region状态变迁的操作以及操作对应的Region状态。其中特定操作行为通常包括assign、unassign、split以及merge等,而很多其他操作都可以拆成unassign和assign,比如move操作实际上是先unassign再assign。

Region状态迁移

Region状态迁移过程有点类似于状态机,也是通过事件驱动的。和Region状态一样,HBase还定义了很多事件(具体见EventType类)。此处以unassign过程为例说明事件是如何驱动状态变迁的,如下图所示。

上图所示是Region在close时的状态变迁图,其中红字部分就是发生的各种事件。可见,如果发生M_ZK_REGION_CLOSING事件,Region就会从OPEN状态迁移到PENDING_CLOSE状态,而发生RS_ZK_REGION_CLOSING事件,Region会从PENDING_CLOSE状态迁移到CLOSING状态,以此类推,发生RS_ZK_REGION_CLOSED事件,Region就会从CLOSING状态迁移到CLOSED状态。

接下来本节以unassign操作为例对这个流程进行解析。

如下图所示,整个unassign操作是一个比较复杂的过程,涉及HMaster、RegionServer和Zookeeper三个组件:

  • HMaster负责维护Region在整个操作过程中的状态变化,起到一个枢纽的作用。它有两个重要的HashMap数据结构,分别为regionStates和regionsInTransition,前者用来存储整个集群中所有Region及其当时状态,而后者主要存储在变迁过程中的Region及其状态,后者是前者的一个子集,不包含OPEN状态的Regions;
  • RegionServer负责接收HMaster的指令执行具体unassign操作,实际上就是关闭region操作;
  • Zookeeper负责存储操作过程中的事件,它有一个路径为/hbase/region-in-transition的节点。一旦一个Region发生unssign操作,就会在这个节点下生成一个子节点,子节点的内容是一个“事件”经过序列化的字符串,并且Master会监听在这个子节点上,一旦发生任何事件,Master就会监听到并更新Region的状态。

  1. HMaster先执行事件M_ZK_REGION_CLOSING并更新RegionStates,将该Region的状态改为PENDING_CLOSE,并在regionsInTransition中插入一条记录;
  2. 发送一条RPC命令给拥有该Region的RegionServer,责令其关闭该Region;
  3. RegionServer接收到HMaster发送过来的命令之后,首先生成一个RS_ZK_REGION_CLOSING事件,更新到Zookeeper,Master监听到ZK节点变动之后更新regionStates,将该Region的状态改为CLOSING;
  4. RegionServer执行真正的Region关闭操作:如果该Region正在执行flush或者compaction,等待操作完成;否则将该Region下的所有Memstore强制flush;
  5. 完成之后生成事件RS_ZK_REGION_CLOSED,更新到Zookeeper,Master监听到ZK节点变动之后更新regionStates,将该Region的状态改为CLOSED。

HMaster上所有Region状态是否持久化取决于参数hbase.assignment.usezk,默认情况下该参数为true,表示使用ZooKeeper情况下并不会对Region状态进行持久化(详见RegionStateStore类)。

Region的这些状态会存储在三个区域:meta表,Master内存,ZooKeeper的region-in-transition节点,并且作用不同。

(1)meta表

只存储Region所在的RegionServer,并不存储迁移过程中的中间状态

  • 如果Region从rs1成功迁移到rs2,那么meta表中仅仅存储Region与rs2的对应关系;
  • 如果迁移中间出现异常,那么meta表就仅仅存储老的Region与rs1的对应关系。

(2)Master内存

master中存储整个集群所有的Region信息,根据这个信息可以得出此Region当前以什么状态在哪个RegionServer上。

Master存储的Region状态变更都是由RegionServer通过ZooKeeper通知给Master的

因此,Master上的Region状态变更总是滞后于真正的Region状态变更。

注意,我们在HBase Master WebUI上看到的Region状态都来自于Master内存信息。

(3)ZooKeeper

存储的是临时性的状态转移信息,作为Master和RegionServer之间反馈Region状态的通道。

如果Master(或者相应RegionServer)在中间某个阶段发生异常,ZooKeeper上存储的状态可以在新Master启动之后作为依据继续进行迁移操作。

只有这三个状态保持一致,对应的Region才处于正常的工作状态。然而,在很多异常情况下,Region状态在三个地方并不能保持一致,这就会出现region-in-transition(RIT)现象。

Region状态变迁异常

再回顾unassign的整个过程就会发现一次完整操作涉及太多流程,任何异常都可能会导致Region处于较长时间的RIT状态,好在HBase针对常见的异常做了最基本的容错处理:

  • Master宕机重启:Master在宕机之后会丢失所有内存中的信息,也包括RIT信息以及Region状态信息,因此在重启之后会第一时间重建这些信息。重启之后会遍历Zookeeper上/hbase/regions-in-transition节点下的所有子节点,解析所有子节点对应的最后一个‘事件’,解析完成之后一方面借此重建全局的Region状态,另一方面根据状态机转移图对处于RIT状态的Region进行处理。比如如果发现当前Region的状态是PENDING_CLOSE,Master就会再次据此向RegionServer发送’关闭Region’的RPC命令。
  • 其他异常宕机:HBase会在后台开启一个线程定期检查内存中处于RIT中的Region,一旦这些Region处于RIT状态的时长超过一定的阈值(由参数hbase.master.assignment.timeoutmonitor.timeout定义,默认600000ms)就会重新执行unassign或者assign操作。比如如果当前Region的状态是PENDING_CLOSE,而且处于该状态的时间超过了600000ms,Master就会重新执行unassign操作,向RegionServer再次发送’关闭Region’的RPC命令。

可见,HBase提供了基本的重试机制,保证在一些短暂异常的情况下能够通过不断重试拉起那些处于RIT状态的Region,进而保证操作的完整性和状态的一致性。然而不幸的是,因为各种各样的原因,很多Region还是会掉入长时间的RIT状态,甚至是永久的RIT状态,必须人为干预才能解决。

永久RIT状态案例分析

通过RIT机制的了解,其实可以发现大部分处于RIT状态的Region都是短暂的,即使在大多数短暂异常的情况下HBase也提供了重试机制保证Region能够很快恢复正常。然而在一些特别极端的场景下还是会发生一些异常导致部分Region掉入永久的RIT状态,进而会引起表读写阻塞甚至整个集群的读写阻塞。

  • 永久性掉入RIT状态其实出现的概率并不高,都是在一些极端情况下才会出现。绝大部分RIT状态都是暂时的。
  • 一旦掉入永久性RIT状态,说明一定有根本性的问题原因,只有定位出这些问题才能彻底解决问题
  • 如果Region长时间处于PENDING_CLOSE或者CLOSING状态,一般是因为RegionServer在关闭Region的时候遇到了长时间Compaction任务或Flush任务,所以如果Region在做类似于Major_Compact的操作时尽量不要执行unassign操作,比如move操作、disable操作等;而如果Region长时间处于FAILED_OPEN状态,一般是因为HDFS文件出现异常所致,可以通过RegionServer日志以及hbck定位出来

案例一:Compaction永久阻塞

问题现象

线上一个集群因为未知原因忽然就卡住了,读写完全进不来了;另外还有很多处于PENDING_CLOSE状态的Region。

问题分析

集群卡住常见原因无非两个,一是Memstore总消耗内存大小超过了上限进而触发RegionServer级别flush,此时系统会阻塞集群执行长时间flush操作;二是storefile数量过多超过设定的上限阈值(参见:hbase.hstore.blockingStoreFiles),此时系统会阻塞所有flush请求而执行compaction。

问题诊断

(1)首先查看了各个RegionServer上的Memstore使用大小,并没有达到设定的upperLimit。

(2)再查看了一下所有RegionServer的storefile数量,瞬间石化了,store数为250的RegionServer上storefile数量竟然达到了1.5w+,很多单个store的storefile都超过了设定阈值100

(3)初步怀疑是因为storefile数量过多引起的,看到这么多storefile的第一反应是手动执行major_compaction,然而所有的compact命令好像都没有起任何作用

(4)无意中发现所有RegionServer的Compaction任务都是同一张表music_actions的,而且Compaction时间都基本持续了一两天。到此基本可以确认是因为表music_actions的Compaction任务长时间阻塞,占用了所有的Compaction线程资源,导致集群中所有其他表都无法执行Compaction任务,最后导致StoreFile大量堆积

(5)那为什么会存在PENDING_CLOSE状态的Region呢?经查看,这些处于PENDING_CLOSE状态的Region全部来自于表music_actions,进一步诊断确认是由于在执行graceful_stop过程中unassign时遇到Compaction长时间阻塞导致RegionServer无法执行Region关闭(参考上文unassign过程),因而掉入了永久RIT。

解决方案

(1)这个问题中RIT和集群卡住原因都在于music_actions这张表的Compaction阻塞,因此需要定位Compaction阻塞的具体原因。经过一段时间的定位初步怀疑是因为这张表的编码导致,anyway,具体原因不重要,因为一旦Compaction阻塞,好像是没办法通过正常命令解除这种阻塞的。临时有用的办法是增大集群的Compaction线程,以期望有更多空闲线程可以处理集群中其他Compaction任务,消化大量堆积的StoreFiles

(2)而永久性消灭这种Compaction阻塞只能先将这张表数据迁移出来,然后将这张表暴力删除。暴力删除就是先将HDFS对应文件删除,再将hbase:meta中该表对应的相关数据清除,最后重启整个集群即可。这张表删除之后使用hbck检查一致性之后,集群Compaction阻塞现象就消失了,集群就完全恢复正常。

案例二:HDFS文件异常

问题现象

线上集群很多RegionServer短时间内频频宕机,有几个Region处于FAILED_OPEN状态

分析诊断

(1)查看系统监控以及RegionServer日志,确认RegionServer频繁宕机是因为大量CLOSE_WAIT状态的短连接导致。监控显示短时间内(4h)CLOSE_WAIT的数量从0增长到6w+。

(2)再查看RegionServer日志查看到如下日志:

2016-07-27 09:42:14,932 [RS_OPEN_REGION-inspur250.photo.163.org,60020,1469581282053-0] ERROR org.apache.hadoop.hbase.regionserver.handler.OpenRegionHandler - Failed open of region=news_user_actions,|u:cfcd208495d565ef66e7dff9f98764da
|1462799167|30671473410714402,1469522128310.3b3ae24c65fc5094bc2acfebaa7a56de., starting to roll back the global memstore size.
java.io.IOException: java.io.IOException: java.io.FileNotFoundException: File does not exist: /hbase/news_user_actions/b7b3faab86527b88a92f2a248a54d3dc/meta/0f47cda55fa44cf9aa2599079894aed6
2016-07-27 09:42:14,934 [RS_OPEN_REGION-inspur250.photo.163.org,60020,1469581282053-0] INFO org.apache.hadoop.hbase.regionserver.handler.OpenRegionHandler - Opening of region {NAME => 'news_user_actions,|u:cfcd208495d565ef66e7dff9f9
8764da|1462799167|30671473410714402,1469522128310.3b3ae24c65fc5094bc2acfebaa7a56de.', STARTKEY => '|u:cfcd208495d565ef66e7dff9f98764da|1462799167|30671473410714402', ENDKEY => '|u:d0', ENCODED => 3b3ae24c65fc5094bc2acfebaa7a56de,} faile
d, marking as FAILED_OPEN in ZK

日志显示,Region ‘3b3ae24c65fc5094bc2acfebaa7a56de’打开失败,因此状态被设置为FAILED_OPEN,原因初步认为是FileNotFoundException导致,找不到的文件是Region ‘b7b3faab86527b88a92f2a248a54d3dc’ 下的一个文件,这两者之间有什么联系呢?

(3)使用hbck检查了一把,得到如下错误信息:

ERROR: Found lingering reference file hdfs://mycluster/hbase/news_user_actions/3b3ae24c65fc5094bc2acfebaa7a56de/meta/0f47cda55fa44cf9aa2599079894aed6.b7b3faab86527b88a92f2a248a54d3dc

从引用文件可以看出来,Region ‘3b3ae24c65fc5094bc2acfebaa7a56de’是‘ b7b3faab86527b88a92f2a248a54d3dc’的子Region。

父Region分裂成两个子Region其实并没有涉及到数据文件的分裂,而是会在子Region的HDFS目录下生成一个指向父Region目录的引用文件,直到子Region执行Compaction操作才会将父Region的文件合并过来。

到这里,就可以理解为什么子Region会长时间处于FAILED_OPEN状态:因为子Region引用了父Region的文件,然而父Region的文件因为未知原因丢失了,所以子Region在打开的时候因为找不到引用文件因而会失败。而这种异常并不能通过简单的重试可以解决,所以会长时间掉入RIT状态。

(4)现在基本可以通过RegionServer日志和hbck日志确定Region处于FAILED_OPEN的原因是因为子Region所引用的父Region的文件丢失导致。那为什么会出现CLOSE_WAIT数量暴涨的问题呢?经确认是因为Region在打开的时候会读取Region对应HDFS相关文件,但因为引用文件丢失所以读取失败,读取失败之后系统会不断重试,每次重试都会同datanode建立短连接,这些短连接因为hbase的bug一直得不到合理处理就会引起CLOSEE_WAIT数量暴涨。

解决方案

删掉HDFS上所有检查出来的引用文件即可。

关于为什么会出现父文件丢失,在此补充一下。目前有可能有几个官方bug触发这个问题,详见[HBASE-13331]和[HBASE-16527]。

简单来说下在split完成之后父region会在什么情况下被删除,实际上Master会启动一个线程定时检查完成split之后的父目录是否可以被有效删除,系统meta表中会记录该父region切分后的子region,只需要检查此两个子region是否还存在引用文件,如果都不存在引用文件就可以认为该父region对应的文件可以被删除。

HBASE-13331 bug是说检查引用文件时候(检查是否存在、检查是否可以正常打开)如果抛出IOException异常,函数就会返回没有引用文件,导致父region被删掉。正常情况下应该保险起见返回存在引用文件,保留父region,并打印日志手工介入查看。

0条评论
0 / 1000
陈****曈
5文章数
0粉丝数
陈****曈
5 文章 | 0 粉丝
陈****曈
5文章数
0粉丝数
陈****曈
5 文章 | 0 粉丝
原创

HBase RIT机制

2023-09-04 06:07:28
45
0

HBase RIT机制,全称为Region in Transition,意指Region变迁机制,实际上是指在一次特定操作行为中Region状态的变迁。

Region状态介绍

HBase在RegionState类中定义了Region的主要状态,如下图所示。

上图中实际上定义了四种会触发Region状态变迁的操作以及操作对应的Region状态。其中特定操作行为通常包括assign、unassign、split以及merge等,而很多其他操作都可以拆成unassign和assign,比如move操作实际上是先unassign再assign。

Region状态迁移

Region状态迁移过程有点类似于状态机,也是通过事件驱动的。和Region状态一样,HBase还定义了很多事件(具体见EventType类)。此处以unassign过程为例说明事件是如何驱动状态变迁的,如下图所示。

上图所示是Region在close时的状态变迁图,其中红字部分就是发生的各种事件。可见,如果发生M_ZK_REGION_CLOSING事件,Region就会从OPEN状态迁移到PENDING_CLOSE状态,而发生RS_ZK_REGION_CLOSING事件,Region会从PENDING_CLOSE状态迁移到CLOSING状态,以此类推,发生RS_ZK_REGION_CLOSED事件,Region就会从CLOSING状态迁移到CLOSED状态。

接下来本节以unassign操作为例对这个流程进行解析。

如下图所示,整个unassign操作是一个比较复杂的过程,涉及HMaster、RegionServer和Zookeeper三个组件:

  • HMaster负责维护Region在整个操作过程中的状态变化,起到一个枢纽的作用。它有两个重要的HashMap数据结构,分别为regionStates和regionsInTransition,前者用来存储整个集群中所有Region及其当时状态,而后者主要存储在变迁过程中的Region及其状态,后者是前者的一个子集,不包含OPEN状态的Regions;
  • RegionServer负责接收HMaster的指令执行具体unassign操作,实际上就是关闭region操作;
  • Zookeeper负责存储操作过程中的事件,它有一个路径为/hbase/region-in-transition的节点。一旦一个Region发生unssign操作,就会在这个节点下生成一个子节点,子节点的内容是一个“事件”经过序列化的字符串,并且Master会监听在这个子节点上,一旦发生任何事件,Master就会监听到并更新Region的状态。

  1. HMaster先执行事件M_ZK_REGION_CLOSING并更新RegionStates,将该Region的状态改为PENDING_CLOSE,并在regionsInTransition中插入一条记录;
  2. 发送一条RPC命令给拥有该Region的RegionServer,责令其关闭该Region;
  3. RegionServer接收到HMaster发送过来的命令之后,首先生成一个RS_ZK_REGION_CLOSING事件,更新到Zookeeper,Master监听到ZK节点变动之后更新regionStates,将该Region的状态改为CLOSING;
  4. RegionServer执行真正的Region关闭操作:如果该Region正在执行flush或者compaction,等待操作完成;否则将该Region下的所有Memstore强制flush;
  5. 完成之后生成事件RS_ZK_REGION_CLOSED,更新到Zookeeper,Master监听到ZK节点变动之后更新regionStates,将该Region的状态改为CLOSED。

HMaster上所有Region状态是否持久化取决于参数hbase.assignment.usezk,默认情况下该参数为true,表示使用ZooKeeper情况下并不会对Region状态进行持久化(详见RegionStateStore类)。

Region的这些状态会存储在三个区域:meta表,Master内存,ZooKeeper的region-in-transition节点,并且作用不同。

(1)meta表

只存储Region所在的RegionServer,并不存储迁移过程中的中间状态

  • 如果Region从rs1成功迁移到rs2,那么meta表中仅仅存储Region与rs2的对应关系;
  • 如果迁移中间出现异常,那么meta表就仅仅存储老的Region与rs1的对应关系。

(2)Master内存

master中存储整个集群所有的Region信息,根据这个信息可以得出此Region当前以什么状态在哪个RegionServer上。

Master存储的Region状态变更都是由RegionServer通过ZooKeeper通知给Master的

因此,Master上的Region状态变更总是滞后于真正的Region状态变更。

注意,我们在HBase Master WebUI上看到的Region状态都来自于Master内存信息。

(3)ZooKeeper

存储的是临时性的状态转移信息,作为Master和RegionServer之间反馈Region状态的通道。

如果Master(或者相应RegionServer)在中间某个阶段发生异常,ZooKeeper上存储的状态可以在新Master启动之后作为依据继续进行迁移操作。

只有这三个状态保持一致,对应的Region才处于正常的工作状态。然而,在很多异常情况下,Region状态在三个地方并不能保持一致,这就会出现region-in-transition(RIT)现象。

Region状态变迁异常

再回顾unassign的整个过程就会发现一次完整操作涉及太多流程,任何异常都可能会导致Region处于较长时间的RIT状态,好在HBase针对常见的异常做了最基本的容错处理:

  • Master宕机重启:Master在宕机之后会丢失所有内存中的信息,也包括RIT信息以及Region状态信息,因此在重启之后会第一时间重建这些信息。重启之后会遍历Zookeeper上/hbase/regions-in-transition节点下的所有子节点,解析所有子节点对应的最后一个‘事件’,解析完成之后一方面借此重建全局的Region状态,另一方面根据状态机转移图对处于RIT状态的Region进行处理。比如如果发现当前Region的状态是PENDING_CLOSE,Master就会再次据此向RegionServer发送’关闭Region’的RPC命令。
  • 其他异常宕机:HBase会在后台开启一个线程定期检查内存中处于RIT中的Region,一旦这些Region处于RIT状态的时长超过一定的阈值(由参数hbase.master.assignment.timeoutmonitor.timeout定义,默认600000ms)就会重新执行unassign或者assign操作。比如如果当前Region的状态是PENDING_CLOSE,而且处于该状态的时间超过了600000ms,Master就会重新执行unassign操作,向RegionServer再次发送’关闭Region’的RPC命令。

可见,HBase提供了基本的重试机制,保证在一些短暂异常的情况下能够通过不断重试拉起那些处于RIT状态的Region,进而保证操作的完整性和状态的一致性。然而不幸的是,因为各种各样的原因,很多Region还是会掉入长时间的RIT状态,甚至是永久的RIT状态,必须人为干预才能解决。

永久RIT状态案例分析

通过RIT机制的了解,其实可以发现大部分处于RIT状态的Region都是短暂的,即使在大多数短暂异常的情况下HBase也提供了重试机制保证Region能够很快恢复正常。然而在一些特别极端的场景下还是会发生一些异常导致部分Region掉入永久的RIT状态,进而会引起表读写阻塞甚至整个集群的读写阻塞。

  • 永久性掉入RIT状态其实出现的概率并不高,都是在一些极端情况下才会出现。绝大部分RIT状态都是暂时的。
  • 一旦掉入永久性RIT状态,说明一定有根本性的问题原因,只有定位出这些问题才能彻底解决问题
  • 如果Region长时间处于PENDING_CLOSE或者CLOSING状态,一般是因为RegionServer在关闭Region的时候遇到了长时间Compaction任务或Flush任务,所以如果Region在做类似于Major_Compact的操作时尽量不要执行unassign操作,比如move操作、disable操作等;而如果Region长时间处于FAILED_OPEN状态,一般是因为HDFS文件出现异常所致,可以通过RegionServer日志以及hbck定位出来

案例一:Compaction永久阻塞

问题现象

线上一个集群因为未知原因忽然就卡住了,读写完全进不来了;另外还有很多处于PENDING_CLOSE状态的Region。

问题分析

集群卡住常见原因无非两个,一是Memstore总消耗内存大小超过了上限进而触发RegionServer级别flush,此时系统会阻塞集群执行长时间flush操作;二是storefile数量过多超过设定的上限阈值(参见:hbase.hstore.blockingStoreFiles),此时系统会阻塞所有flush请求而执行compaction。

问题诊断

(1)首先查看了各个RegionServer上的Memstore使用大小,并没有达到设定的upperLimit。

(2)再查看了一下所有RegionServer的storefile数量,瞬间石化了,store数为250的RegionServer上storefile数量竟然达到了1.5w+,很多单个store的storefile都超过了设定阈值100

(3)初步怀疑是因为storefile数量过多引起的,看到这么多storefile的第一反应是手动执行major_compaction,然而所有的compact命令好像都没有起任何作用

(4)无意中发现所有RegionServer的Compaction任务都是同一张表music_actions的,而且Compaction时间都基本持续了一两天。到此基本可以确认是因为表music_actions的Compaction任务长时间阻塞,占用了所有的Compaction线程资源,导致集群中所有其他表都无法执行Compaction任务,最后导致StoreFile大量堆积

(5)那为什么会存在PENDING_CLOSE状态的Region呢?经查看,这些处于PENDING_CLOSE状态的Region全部来自于表music_actions,进一步诊断确认是由于在执行graceful_stop过程中unassign时遇到Compaction长时间阻塞导致RegionServer无法执行Region关闭(参考上文unassign过程),因而掉入了永久RIT。

解决方案

(1)这个问题中RIT和集群卡住原因都在于music_actions这张表的Compaction阻塞,因此需要定位Compaction阻塞的具体原因。经过一段时间的定位初步怀疑是因为这张表的编码导致,anyway,具体原因不重要,因为一旦Compaction阻塞,好像是没办法通过正常命令解除这种阻塞的。临时有用的办法是增大集群的Compaction线程,以期望有更多空闲线程可以处理集群中其他Compaction任务,消化大量堆积的StoreFiles

(2)而永久性消灭这种Compaction阻塞只能先将这张表数据迁移出来,然后将这张表暴力删除。暴力删除就是先将HDFS对应文件删除,再将hbase:meta中该表对应的相关数据清除,最后重启整个集群即可。这张表删除之后使用hbck检查一致性之后,集群Compaction阻塞现象就消失了,集群就完全恢复正常。

案例二:HDFS文件异常

问题现象

线上集群很多RegionServer短时间内频频宕机,有几个Region处于FAILED_OPEN状态

分析诊断

(1)查看系统监控以及RegionServer日志,确认RegionServer频繁宕机是因为大量CLOSE_WAIT状态的短连接导致。监控显示短时间内(4h)CLOSE_WAIT的数量从0增长到6w+。

(2)再查看RegionServer日志查看到如下日志:

2016-07-27 09:42:14,932 [RS_OPEN_REGION-inspur250.photo.163.org,60020,1469581282053-0] ERROR org.apache.hadoop.hbase.regionserver.handler.OpenRegionHandler - Failed open of region=news_user_actions,|u:cfcd208495d565ef66e7dff9f98764da
|1462799167|30671473410714402,1469522128310.3b3ae24c65fc5094bc2acfebaa7a56de., starting to roll back the global memstore size.
java.io.IOException: java.io.IOException: java.io.FileNotFoundException: File does not exist: /hbase/news_user_actions/b7b3faab86527b88a92f2a248a54d3dc/meta/0f47cda55fa44cf9aa2599079894aed6
2016-07-27 09:42:14,934 [RS_OPEN_REGION-inspur250.photo.163.org,60020,1469581282053-0] INFO org.apache.hadoop.hbase.regionserver.handler.OpenRegionHandler - Opening of region {NAME => 'news_user_actions,|u:cfcd208495d565ef66e7dff9f9
8764da|1462799167|30671473410714402,1469522128310.3b3ae24c65fc5094bc2acfebaa7a56de.', STARTKEY => '|u:cfcd208495d565ef66e7dff9f98764da|1462799167|30671473410714402', ENDKEY => '|u:d0', ENCODED => 3b3ae24c65fc5094bc2acfebaa7a56de,} faile
d, marking as FAILED_OPEN in ZK

日志显示,Region ‘3b3ae24c65fc5094bc2acfebaa7a56de’打开失败,因此状态被设置为FAILED_OPEN,原因初步认为是FileNotFoundException导致,找不到的文件是Region ‘b7b3faab86527b88a92f2a248a54d3dc’ 下的一个文件,这两者之间有什么联系呢?

(3)使用hbck检查了一把,得到如下错误信息:

ERROR: Found lingering reference file hdfs://mycluster/hbase/news_user_actions/3b3ae24c65fc5094bc2acfebaa7a56de/meta/0f47cda55fa44cf9aa2599079894aed6.b7b3faab86527b88a92f2a248a54d3dc

从引用文件可以看出来,Region ‘3b3ae24c65fc5094bc2acfebaa7a56de’是‘ b7b3faab86527b88a92f2a248a54d3dc’的子Region。

父Region分裂成两个子Region其实并没有涉及到数据文件的分裂,而是会在子Region的HDFS目录下生成一个指向父Region目录的引用文件,直到子Region执行Compaction操作才会将父Region的文件合并过来。

到这里,就可以理解为什么子Region会长时间处于FAILED_OPEN状态:因为子Region引用了父Region的文件,然而父Region的文件因为未知原因丢失了,所以子Region在打开的时候因为找不到引用文件因而会失败。而这种异常并不能通过简单的重试可以解决,所以会长时间掉入RIT状态。

(4)现在基本可以通过RegionServer日志和hbck日志确定Region处于FAILED_OPEN的原因是因为子Region所引用的父Region的文件丢失导致。那为什么会出现CLOSE_WAIT数量暴涨的问题呢?经确认是因为Region在打开的时候会读取Region对应HDFS相关文件,但因为引用文件丢失所以读取失败,读取失败之后系统会不断重试,每次重试都会同datanode建立短连接,这些短连接因为hbase的bug一直得不到合理处理就会引起CLOSEE_WAIT数量暴涨。

解决方案

删掉HDFS上所有检查出来的引用文件即可。

关于为什么会出现父文件丢失,在此补充一下。目前有可能有几个官方bug触发这个问题,详见[HBASE-13331]和[HBASE-16527]。

简单来说下在split完成之后父region会在什么情况下被删除,实际上Master会启动一个线程定时检查完成split之后的父目录是否可以被有效删除,系统meta表中会记录该父region切分后的子region,只需要检查此两个子region是否还存在引用文件,如果都不存在引用文件就可以认为该父region对应的文件可以被删除。

HBASE-13331 bug是说检查引用文件时候(检查是否存在、检查是否可以正常打开)如果抛出IOException异常,函数就会返回没有引用文件,导致父region被删掉。正常情况下应该保险起见返回存在引用文件,保留父region,并打印日志手工介入查看。

文章来自个人专栏
陈金曈的专栏
5 文章 | 2 订阅
0条评论
0 / 1000
请输入你的评论
1
1