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
编译成功后的截图:
Base-hbck2的target目录下可以找到我们最后需要的jar
把该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
运行启用表命令:
hbase hbck -j hbase-hbck2-1.1.0-SNAPSHOT.jar setTableState leo_test ENABLED
看图,表的状态已经被更改为ENABLED
有个疑问就是,表状态被更改为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
命令执行的结果是:
返回值为-1,说明命令运行失败。
十有八九是我的region name指定错了,重新运行如下命令。
hbase hbck -j hbase-hbck2-1.1.0-SNAPSHOT.jar assigns -o 596a8c918380a9fb55ed64ecf716ecd6
命令执行的结果是:
可以看到,成功返回了此次procedure的ID,观察HBase自带的监控界面。
HBCK2的命令提交成功后,监控界面会显示此次操作的记录,里面可以查看命令运行的详细状态。
查看表的监控界面,发现我们操作的region依然在72那台机器上,看起来好像没有任何变化。不知道是不是由于我们测试的表只有一个region的缘故,于是,我又测试了一张有17个region的表。
除了master有这样的日志之外,还是没有任何效果。
暂时实在搞不明白这条命令的具体效果,以后再慢慢研究吧,接着来看下一个核心功能。
5.3 unassigns [OPTIONS] ...
将一个或多个region unassign,返回值是创建的pid则为成功,-1则为失败。
参数解析:
-o,--override,与assigns的一致