加载中…
正文 字体大小:

HBase长期无效unassigned Region哪里来?

(2012-11-05 20:50:20)
标签:

hbase

unassigned

bug

it

分类: 海量数据存储与处理
对于一个曾经运维过几百个节点的HBase集群的运维人员,并且Request每秒在5w以上,一定遇到过如下类似的问题。
ZooKeeper服务在不停地报警指示在zookeeper的unassigned路径由一些节点在会一直存在,而且它的版本在不断增加。此时,HRegionServer和HMaster都会打印大量log,而且会持续给ZooKeeper带来压力,另外整个HBase集群没有报告出现任何Region offline的现象。如果你也是遇到同样的问题,那么请继续看本文的内容。
背景:
注册到zookeeper的unassgined路径下的节点,是处于Transition状态的Region,这主要有如下几种:
 public enum State {
      OFFLINE,        // region is in an offline state
      PENDING_OPEN,   // sent rpc to server to open but has not begun
      OPENING,        // server has begun to open but not yet done
      OPEN,           // server opened region and updated meta
      PENDING_CLOSE,  // sent rpc to server to close but has not begun
      CLOSING,        // server has begun to close but not yet done
      CLOSED,         // server closed region and updated meta
      SPLITTING,      // server started split of a region
      SPLIT           // server completed split of a region
    }
几个常见场景:
1)在一个RegionServer下线,在进行了log split之后,它上面的Region需要迁移到其它RegionServer的时候,会首先将其放入PENDING_OPEN的Region放入unassigned路径下。
2)在Region进行split时,会有Region经历SPLITTING -〉SPLIT的过程,对于SPLIT的操作,下面将努力还原这个过程。
HRegionServer有两种方式触发split操作:
1)用户直接通过API指定splitkey,然后进行Region Split
2)HRegionServer上CompactionSplitThread被触发。
无论哪种方式,最后的核心处理逻辑都是类似的,都是由SplitTransction来进行。
核心操作的步骤为:
1)创建两个子女Region。此时,Parent Region的信息被创建在unassgined路径下,状态为SPLITTING,此时该Region处于Off-line。
2)让两个子女Region上线。在first region 和 second Region上线的选择中,https://issues.apache.org/jira/browse/HBASE-4335 给出了一个小小的trick,让second Region先上线。
orignal Region:[starkey, endkey)  example  {a, b ,c}
first Region : [startkey,midkey)  example {a}
second Region: [midkey, endkey)   example {b, c}
如果让first Region 先于 second Region上线,那么根据Get(key)查找离key最匹配的Region的区间时,会根据startkey进行匹配,由于second Region还没上线,则get(c)最后直接会在first Region中查找,找不到该值,直接返回null,而如果second Region先于first Region上线,则get(a)仍然会找到original Region,从而触发客户端的retry。
3)结束整个split操作工作。这一步相当于打扫卫生的工作,然而就是这步操作,出现了一个问题。
SplitTransaction将parent region的状态由SPLITTING 转换成SPLIT,这是在提醒HMaster端的AssignmentManager,你可以回收这个parent region了。
AssignmentManager由nodeChanged发现了SPLIT的event之后,立刻就开始清理工作,它通过ExecutorThreadPool提交了SplitRegionHandler,接下来它的顺序就特别重要了:
1)它会清空在AssignmentManager内存中该Parent Region记录的状态;
2)然后删除unassigned节点的内容。注意这个步骤是time-consuming过程。
同时,在SplitTransaction内,如果在sleep 100 ms之后,会醒来,如果发现AssignmentManager没有处理该路径,会重新创建一个新的version,状态仍然是SPLIT。可怕的事情是,如果ZooKeeper是顺序执行这个操作,如果某个时序上,AssignmentManager删除了该路径,而此时,HRegionServer上SplitTransaction又正好更新该ZNode,就悲剧了。
此时,AssignmentManager由于内存已经清空了该数据,不再认定该Region是正常的Region,所以,就会报出Warning,而SplitTransaction只是100ms反复更新znode。分布式交互的死循环即将开始。


对于该bug,深层次原因在于,对于zookeeper上一个node的创建与修改都是加锁的,而且是time-consuming的过程。如果在HMaster节点和HRegionServer节点高并发,多线程调度情况下,很容易出现上述的状态。
基于此,我的解决方案是:
增加HRegionServer上SplitTransaction的sleep的时间,可以由100ms改成4000ms,让等待时间足够长,同时保留之前循环检查来比避免ZK的event丢失问题。
hbase-0.92.1 SplitTransaction.java
412 Thread.sleep(100);   => Thread.sleep(4000);

注意,由于分裂的Region已经上线,修改该时间,不会带来性能上的影响。只是确保HMaster的AssignmentManager 可以更好进行相应的操作。

ps:对于该问题,我在hbase 的apache上创建了一个jira,大家可以跟进,看社区怎么看。https://issues.apache.org/jira/browse/HBASE-7101
----------------------------------------------------------------------------
如果你需要解决大数据的难题,hbase,hadoop, Storm等,欢迎一起讨论。
jiangbinglover@gmail.com





阅读 评论 收藏 转载 喜欢 打印举报
已投稿到:
  • 评论加载中,请稍候...
发评论

       

    验证码: 请点击后输入验证码 收听验证码

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

      

    新浪BLOG意见反馈留言板 不良信息反馈 电话:4006900000 提示音后按1键(按当地市话标准计费) 欢迎批评指正

    新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

    新浪公司 版权所有