HBase2.0的修复工具HBCK2

1. 背景

在了解HBCK2之前,建议先了解一下啥是HBCK。HBCK是HBase1.x中的命令,到了HBase2.x中,HBCK命令不适用,且它的写功能(-fix)已删除,它虽然还可以报告HBase2.x集群的状态,但是由于它不了解HBase2.x集群内部的工作原理,因此其评估将不准确。因此,如果你正在使用HBase2.x,那么对HBCK2应该需要了解一些,即使你不经常用到。

2. 获取HBCK2

HBCK2已经被剥离出HBase成为了一个单独的项目,如果你想要使用这个工具,需要根据自己HBase的版本,编译源码。其GitHub地址为:https://github.com/apache/hbase-operator-tools.git

默认HBase的版本是2.1.6,可以在父pom.xml文件里修改成你需要的版本,我们线上集群的版本是cdh-6.3.1-hbase2.1.0,与默认版本接近,因此我就使用默认的版本。

项目根目录下运行打包命令:


mvn clean install -DskipTests

编译成功后的截图:

image-20200527163300460

Base-hbck2的target目录下可以找到我们最后需要的jar

image-20200527163419002

把该jar包上传到集群随便一个目录下。

3. 测试命令是否可以正常使用

开始使用HBCK2的命令,最直接的使用方式:


./bin/hbase hbck -j  <命令>

使用HBCK2禁用启用测试表。

运行禁用表命令:


hbase hbck -j hbase-hbck2-1.1.0-SNAPSHOT.jar setTableState leo_test DISABLED

  • hbase hbck -j hbase-hbck2-1.1.0-SNAPSHOT.jar 指定jar包的方式使用HBCK2命令

  • setTableState 改变表状态的命令

  • leo_test 表名

  • DISABLED 禁用状态

看图,表的状态已经被更改为DISABLED

image-20200527164346921

运行启用表命令:


hbase hbck -j hbase-hbck2-1.1.0-SNAPSHOT.jar setTableState leo_test ENABLED

看图,表的状态已经被更改为ENABLED

image-20200527164512826

有个疑问就是,表状态被更改为DISABLED,这张表的region依然是online状态,表依然可以被正常查询。

以上操作顺利执行,就可以证明我们的HBCK2命令被安装成功了。

4. Procedure简介

HBase2集群几乎所有的操作都是通过procedure进行的,因此,HBCK2的工作实际就是修复各种不正常的procedure。

一个procedure是由一系列的操作组成,一旦完成,要么成功,要么失败(ROLL BACK),不存在中间状态,所以,procedure是支持事物的。

procedure执行的每一步都会以log的形式持久化在HBase的MasterProcWals目录下,这样master重启时也能通过日志来恢复之前的状态且继续执行。

对于运维而言最重要的一点就是procedure在执行过程中会拿好几把锁, 这个在处理问题时是很重要的,因为一旦锁没有释放,再做任何操作也只能是卡住等锁。

  • IdLock:procedure级别的锁,保证一个procedure不会被多个线程同时执行。

  • 资源锁:对HBase的内部资源进行加锁,不同的procedure加锁的粒度不同,目前有region/table/namespace/region server级别的锁。

举例来说,假设我assign一个region,那么procedure在执行的时候就需要对这个region进行加锁,这样如果有别的人想要unassign这个region,或者drop这个region所在的table,都需要等最早的assignment结束后释放锁了才能执行。这样防止有不一致的情况出现。

5. HBCK2核心功能介绍

5.1 bypass [OPTIONS] ...

bypass可以将一个或多个卡住的procedure进行释放。

原理是,在procedure的类里有一个bypass的flag,每次执行时会检查这个flag是否为true,如果为true则直接返回null,这样procedure就会被认为执行成功。

而bypass就是把这个procedure对象中的这个flag设为true。这样stuck的procedure就能够不再执行,后续的修复才能继续。

返回值为true则是成功,false是失败。

参数解析:

-o,--overide

在执行bypass之前先会尝试去拿idLock,如果procedure还在运行就会超时返回null,但是设置了这个参数,即使拿不到idLock也会去将procedure的bypass flag设为true。

-r, --recursive

在bypass一个procedure时也会将这个procedure的所有子procedure进行递归bypass是。例如我们bypass一个对table schema修改的procedure,就需要加上-r参数,才能把这个操作的所有子procedure都bypass掉。

-w, --lockWait

上面提到的等到idLock的超时时间配置,默认为1ms。

5.2 assigns [OPTIONS] ...

将一个或多个region再次随机assign到别的机器上,返回值时创建的pid则为成功,-1则为失败。

参数解析:

-o, --override

这里的override跟bypass的override不同,因为assign本身就会创建一个新的procedure,所以肯定是不涉及到拿idLock的,但是这里涉及到资源锁的问题。因为之前卡住的资源锁即使在bypass后也不会释放(用于fence, 防止更多未知的错误操作),所以需要加一个-o去手动释放这个资源锁。

下面,我们实际运行一下这个命令,感受其作用。


hbase hbck -j hbase-hbck2-1.1.0-SNAPSHOT.jar assigns -o leo_test,,1588902855503.596a8c918380a9fb55ed64ecf716ecd6.

  • leo_test,,1588902855503.596a8c918380a9fb55ed64ecf716ecd6. 这个是我测试表,leo_test的一个region的encoded_name

命令执行的结果是:

image-20200527174818532

返回值为-1,说明命令运行失败。

十有八九是我的region name指定错了,重新运行如下命令。


hbase hbck -j hbase-hbck2-1.1.0-SNAPSHOT.jar assigns -o 596a8c918380a9fb55ed64ecf716ecd6

命令执行的结果是:

image-20200527175043176

可以看到,成功返回了此次procedure的ID,观察HBase自带的监控界面。

image-20200527175200833

HBCK2的命令提交成功后,监控界面会显示此次操作的记录,里面可以查看命令运行的详细状态。

查看表的监控界面,发现我们操作的region依然在72那台机器上,看起来好像没有任何变化。不知道是不是由于我们测试的表只有一个region的缘故,于是,我又测试了一张有17个region的表。

除了master有这样的日志之外,还是没有任何效果。

image-20200527180214854

暂时实在搞不明白这条命令的具体效果,以后再慢慢研究吧,接着来看下一个核心功能。

5.3 unassigns [OPTIONS] ...

将一个或多个region unassign,返回值是创建的pid则为成功,-1则为失败。

参数解析:

-o,--override,与assigns的一致

5.4 setTableState

可能的table状态, ENABLED, DISABLED, DISABLING, ENABLING

在table的状态和所有的region状态不一致时可以用这个命令进行修复

5.5 serverCrashProcedures ...

手动schedule一个或多个serverCrashProcedure, 如果有serverCrashProcedure没有执行成功,但是procedure log已经丢失了,那么可以利用这个命令进行修复。返回值为创建的pid则为成功,-1则为失败。

patch在HBASE-21393[3],目前这个功能在release版本还没有。

image-20200527181148089

看样子应该能用,可现在就是不知道咋用。

6. 利用HBCK2来查找集群的问题

6.1 canary tool

模拟用户的读写请求,去访问集群上的表。当我们需要检查集群meta上记录的region assignment跟实际region server上打开的region是否一致时,可以使用这个命令去检查:


hbase canary -f false -t 6000000

nohup hbase canary -f false -t 6000000 > /data/leo_jie/hbase.log 2>&1 &

这个命令会向meta上的记录的每个region发送一个get请求,将-f设为false是为了不在遇到第一个错误时退出,-t则是这个命令的超时时间,我们设成了6000秒。在执行完成以后可以通过grep ERROR来找到那些有问题的region。

需要注意的是因为是模拟客户端发送的get请求,最好将HBase的客户端超时时间和超时次数配的小一些,否则会很慢。

PS: canary 本身也很适合用来作为集群可用性的监控,有兴趣的同学可以去了解一下。


cat /data/leo_jie/hbase.log | grep ERROR

grep ERROR 来发现是否有异常信息。

6.2 页面状态

其实大部分的信息都会在master的页面上展示出来,我们来详细的介绍一下:

image-20200527181721474

可以检查当前所有没有执行完的procedure以及所有资源锁,当我们想要assign或者unassign一个region时,需要先去检查下是由有别的procedure已经占有了这个资源锁,如果是的话需要现将那个procedure bypass掉,或者等待那个procedure释放锁。

image

可以看到EXCLUSIVE的lock只有region级别的,图中红框圈出来的就是占有这个锁的procedure id以及它的parent procedure id, 由此我们知道如果想要重新assign/unassign这个region,那么一定要bypass这个procedure。

同理,当Locks这块没有任何EXLUSIVE锁时,我们可以放心的去执行操作而不用担心被卡住。

以上内容节选自,HBase指南 | HBase 2.0之修复工具HBCK2运维指南,因为我在本地测试的时候,没有重现这种锁占用的情况。

6.3 OPENING/CLOSING region的查找

branch-2.0 上最容易出现的问题就是region卡在了OPENNING/CLOSING状态,一般处于这两种状态的region都会在rit的队列中,可以通过点击页面上的链接拿到所有的region以及对应的procedure id。

image

可以看到现在有17个region处在transition中,我们可以点击红框圈住的这个链接,会展示所有的region。

image

因为我们最后是希望通过HBCK2来进行处理,那么最好是可以复制粘贴需要处理的region或者procedure, 所以可以点击圈出的这两个按钮,会以text形式展示所有region或者所有procedure。

image

以上内容依旧是节选,因为没遇到RIT的情况,同时,我们也不希望遇见。

6.4 Master的日志

stuck的region会打印以下日志:


WARN [ProcExecTimeout] org.apache.hadoop.hbase.master.assignment.AssignmentManager: STUCK Region-In-Transition rit=OPENING, location=c4-hadoop-tst-st99.bj,42900,1542148656901, table=test_modify, region=8d81f74b324d0503c3fc87f34e9a17cb

7.解决问题

定位到问题之后,我们需要解决问题。

7.1 解决region卡在OPENING/CLOSING 状态

首先找到这些region对应的pid, 然后执行bypass, 检查是否锁都释放了,如果释放了就再assign一遍,如果需要close,就再unassign一次。

7.2 对table的修改有问题如何回退

找到这个修改的root procedure, bypass -or来bypass所有相关的procedure, 利用table unset来重置meta,因为bypass之后资源锁还是没有释放,所以需要手动加上override参数再去全部assigns一遍

7.3 Master起不来

日志里一般会有这个:


WARN org.apache.hadoop.hbase.master.HMaster: hbase:meta,,1.1588230740 is NOT online; state={1588230740 state=CLOSING, ts=1538456302300, server=ve1017.example.org,22101,1538449648131}; ServerCrashProcedures=true. Master startup cannot progress, in holding-pattern until region onlined.

手动去assign一下meta表即可,hbase:meta表的encoded name是一个时间戳,比如上面日志的encoded name就是1588230740

另外hbase:namespace表没有online也会造成这个问题,同样需要我们去手动assign一下

7.4 table卡在disabling状态

因为要求是所有region都disabled, 那么解决办法可以是手动把没有closed的region根据case1来解决。如果所有region都已经是closed状态了,那么我可以利用setTableState手动将表的状态设为DISABLED。之后再drop都是安全的了。

8. 总体的解决思路

其实HBase-2.x版本的运维思路很简单,因为使用了procedure,集群出现meta跟regionserver不一致的状态是很少的,一般都是有procedure出问题了。那么我们主要就是看怎么解决这个有问题的procedure。

如果是table/namespace级别的修改,因为设计到很多region的锁,如果需要bypass的话需要找到root procedure然后使用bypass -or.

如果只是region级别的问题,则bypass -o即可。

bypass之后检查locks的页面,看看是不是锁都释放了,如果没有锁了则根据需求进行assign或者unassign,或者对table的属性进行还原。

9. 参考链接

文中很多解决问题的思路参考了一下博客,后续实践中如果遇到此类问题,将会进行更加详细的分析和总结,然后补充文档。

  • HBase指南 | HBase 2.0之修复工具HBCK2运维指南

你可能感兴趣的:(HBase2.0的修复工具HBCK2)