HBase补充学习(二)

一、前言

前面自查出过一篇HBase补充学习(一),最近算是实战的过程中发现了一些其他的自己学习的时候尚未注意到的点,有的很简单但是以前尚未意识到的点,有的从未学习过顺便学习到的点,以此开一篇博客进行记录。不定时更新~

二、补充内容

2.1 HBase Shell与HBase API的思想问题

遇到了一个问题,在程序端已经实现通过API查看HBase表,但有一个需求需要去回到命令行进行查看,但是拥有的信息是表名、列族名和列名和一个value值,需要对value为依据进行模糊查询,在API中使用SingleColumnValueFilter过滤器完成,但如何在Shell中实现想了好久,一度以为Shell不支持过滤器以及单值过滤、通配符、模糊查询等等

真的是个很低级的意识错误,试想API的产生就是为那些不习惯操纵命令行的人员提供便利,实际上就是对Shell命令的一个封装,执行API实际上底层也是执行Shell命令,那么既然API支持的东西在Shell命令中自然也是支持的,于是进行一番查找,果真是有的。这是一个意识错误,值得记录。

//API操作
SingleColumnValueFilter filter =
                    new SingleColumnValueFilter(Bytes.toBytes(column_family_name), Bytes.toBytes(column_name), CompareOperator.EQUAL, Bytes.toBytes(value));

//Shell命令
scan 'table_name',{FILTER=>"SingleColumnValueFilter('cf_name','cq_name',=,'substring:value')"}

举个例子,hbase_test表中有一个f列族,列族中有placeno和devmac两个列,现在对devmac使用单列值过滤器,将所有demac值子串中含有3524子串的行输出,语法如下,结果可以看到过滤器使用成功,将所有包含3524的row1和row2输出(值得注意的是输出的是符合条件的所有的行的所有列,如row1行把placeno也输出了)这个单值过滤器很好用,适用于只了解单列值的情况下对表进行过滤扫描出符合条件的所有数据。

再加一个与正则表达式匹配,顺便学习正则语法:https://www.runoob.com/regexp/regexp-syntax.html

^单纯表示正则表达式的开头,*表示前面的那个字符可没有可有一次可有多次,所以下图第一句是匹配所有子串至少存在3524的数据,第二句是匹配所有子串至少存在35245的数据。

2.2 HBase数据输出文本格式问题

有一个需求是需要hbase scan扫描的结果输出到文本格式方便查看,百度搜索使用echo命令完成,过程中遇到一个小问题值得记录,echo中如果scan命令使用到了""需要使用转义字符,否则echo会报错。

如下图,在linux命令行中输入echo命令,将scan的结果输出到myTest.txt中:

echo "scan 'hbase_test',{FILTER=>\"SingleColumnValueFilter('f','devmac',=,'substring:3524')\"}" | ./hbase shell > myTest.txt

查看导入scan结果的myTest.txt:可以发现结果是会显示hbase的进入shell命令、版本、scan命令以及scan结果。

如果没有使用转义符,会提示bash: syntax error near unexpected token `('

尝试过将FILTER后的SingleColumnValueFilter双引号改为单引号,echo命令执行成功,但是最后生成的txt文件会显示scan命令有误。(有误的原因是scan的FILTER读不出单引号下的SingleColumnValueFilter)

2.3 短暂性RIT问题

项目中HBase运行的时候通过网页监控查看到很多table所在的onlineregion为0,也即所在的region没上线,但这个时候hbase集群中的所有regionserver实际上都是正常上线的,区别是每个regionserver上的region数相比之前大大减少,在Web界面可看到的是有一部table属于RIT状态(Region In Transition空洞状态),发现上述有些onlineregion为0的表所在的region都处于RIT状态,需要解决region的RIT状态(长期处于RIT状态,将影响数据的读取)。另外发现一点就是这些region都正处于PENDING_OPEN状态,如何解决这个问题?

实际上这个要回归于HBase Region的split和compact机制(参考HBase补充学习(一)region切分和合并部分),在region分割之后,子region和父region间,查子region的数据实际上是子region通过reference文件找到父region对应的hfile查找,只有当compact的时候会将hfile中的数据转移到子region对应的hfile中,再定期去删除reference。而region在上线是会经历pending-open、opening最后到open状态表明完成上线(close过程参考http://hbasefly.com/2016/09/08/hbase-rit/),Web页面上可见region处于pending-open状态,说明region在上线的过程中出现了问题,使用HBase提供的hbck工具(检查.META.表,hbase hbck命令)来检查hbase集群的数据一致性问题(以region为单位进行一致性检查)。

更多使用方法可参考:https://www.zhyea.com/2017/07/29/hbase-hbck-usage.html

                                    https://blog.csdn.net/oppo62258801/article/details/84246409

首先在hbase/bin下使用hbase hbck 'table_name'查看该表所在region的运维日志,根据日志排查处于pending-open的原因,经过排查发现是查不到reference文件,

这个时候有两种可能性。第一种排查子region对应的父region还在不在(在hdfs目录下查看),如果不在则直接删除reference文件(说明此时子region已经有了分割继承的数据,但最好还是备份一下reference以免误判)并使用assgin 'sub_region'重新上线子region;第二种如果父region还在(一定不要删Reference!此处切记切记一定不要相信网站上一搜ERROR:Found lingering reference file前几篇超级雷同文章的第二方案选择删除reference,要是删了老哥们就找不到数据了,可能解决的方法就是凭记忆/.META.找到父region然后重新分割或者父region到子region数据赋值?千万别轻易删东西!!),使用命令hbase -hbck -fixReferenceFiles 'table_name'修复,如果还不行使用hbase -hbck -fixAssignments 'table_name'重新分配region。(实际上这个hbase机制有关,可能等它自己更新compact一下就可解决,但是如果长期是处于RIT,就得用用hbck工具查查哪出了问题,根据打印日志中的ERROR去排查解决问题)

后面可能是等待了一会hbase自动给好了,初步猜测可能是比较巧的遇到了hbase region上线的时期(hbase自带hbck功能,碰巧亲眼遇到了短暂的RIT,以为是永久RIT所以去进行了排查...不过也庆幸是短暂RIT)

解决问题参考链接:https://blog.csdn.net/lvwenyuan_1/article/details/78579116

解决这个问题的感悟:遇到甲方的问题先往简单的错误上排查,别轻易给自己加难度。就拿这个RIT问题来讲,首先得有RegionServer启动后其上的Region是慢慢启动的基本认知,这个启动过程并非一蹴而就,启动过程中需要经历pending-open、opening和ope状态,那么很有可能在某个过程去看恰好遇到一部分region正处于启动状态,所以首先可以让等5-10分钟再进行查看,看看是否RIT有减少,如果有说明确实刚刚是遇到短暂RIT了,如果没有或者还有增加那么就需要撸起袖子用上hbck进行排查了。(同时还有一点注意到Web页面上的一些时间很重要,可以获得他是啥时候启动的关键点,要是早点看到或许可以早些联想到现在集群正处于启动排列期,人很有可能是查看刚好遇到了region排列等待open时期)

2.4 永久性RIT问题

说来也巧,2.3遇到region短暂处于状态转移rit以为是出现了问题进行排查,后续发现只是恰好碰到hbase中region短期切分region状态转变处于短期region in transition(迁移状态),region迁移之后即会恢复正常。

HBase中region会因为切分、合并、上线、下线等都需要时间而存在短期的rit、空洞、不一致等,只要是短期那么就是正常的。但是如果处于长期RIT,那么一定是有问题了,且这个问题需要人为排查定位干预解决,不然会影响hbase正常的使用。最近就遇到几个region处于永久RIT的问题了,也算是费了不少时间去研究,学到了不少东西,在此进行记录。

确保.META.、table、hdfs保持一致,以下为上面思路的具体执行过程记录。

1. 一开始是查看HBase的60010web页面,发现有三个region处于RIT状态,以为是2.3问题正好碰见region迁移,示意等待5-10mins后再进行查看,但是到时间了甲方也多次重启HBase,这三个region依旧处于RIT状态,基本确定是出问题了,永久RIT问题。

2. 使用hbck工具,定位具体的error,但是由于数据库的表很多,然后也有region可能处于短暂rit状态,导致hbck中很多region都有问题(空洞、表不一致、region chain有问题等等),让人无从下手产生恐惧心理。

3. 后续查阅资料确定较为明确的排查路线,使用hbase hbck 'table_name'精准定位排查一张表的问题,发现是meta上没有regioninfo,使用相关的修复命令没用,所以手动去hbase shell中scan .META.表想要查看是否有这个region,如果没有则使用hbase hbck -fixMeta(删除HDFS没有.META.有的,添加HDFS有但是.META.没有的regioninfo)但是没用。执行hbck没用的时候就需要手动去.META.、HDFS查人工对比进行分析修复

4. 后续想删除zookeeper底下的/hbase/region-in-transition节点然后重启hbase重新assign region,但是./hbase zkcli好不容易进入zookeeper shell(这里真的是挺不好意思的,因为使用的是hbase自带的zookeeper,一时竟不知道咋进入zookeeper shell),ls /hbase发现没有这个节点(这个就很迷,网上资料基本都是有这个节点,我的就没有??),有一个/hbase/unassigned节点,打开发现就是rit状态的region,手动删除重启hbase,结果没用。

5. 由于对问题排查方法的不够精确(没有具体到表)以及对基本操作命令的不熟悉(hdfs、hbase、zookeeper)导致前面浪费了很多时间,最后也是尝试了hbck常见的修复命令没用,后面联想到这个数据本身只是表示某一天的数据,不影响全局,就直接在hbase shell执行disable 'table_name'禁用掉表,问题算是解决了吧。如果后续出现插入数据找不到表的问题(因为业务中有同步数据到HBase的部分),就直接将这三个表delete掉,程序重新创建表插入数据即可。

此处将用到的知识进行总结:

1. HBase region状态转换机制:https://www.cnblogs.com/zackstang/p/9965920.html 正常情况下由于region的assign、unassign、split、merge等操作都需要时间而且随时都有可能发生,只要发生就意味着此时这个region处于迁移状态,直观来讲就是这个region在web页面在region-in-transitiion模块中。所以遇到RIT不要怕,先等上一会看是否是短暂的rit;如果不是那么定位问题分析问题解决问题

2. HBase hbck检查维修工具的常用命令:https://www.zhyea.com/2017/07/29/hbase-hbck-usage.html 一般情况使用hbck最好定位到某一张可以确定有问题的表,节约时间提高效率并且避免遇到短暂RIT的region混淆视听影响判断。常用的命令hbck 'table_name'查看分析问题,根据日志中的ERROR定位问题;hbck -fixAssignments 'table_name' 重新分配region;hbck -fixMeta修复.META.数据表中的regioninfo等信息;hbck -repair多种命令的混合体,一般生产环境少用(未知效果未知操作不要做)

3. HDFS文件的常用命令:https://blog.csdn.net/majianxiong_lzu/article/details/89174176 这里需要声明的一个就是运行命令都最好去bin目录下,使用 ./XXXX来执行(如果有配系统环境,那随意目录都可)常用命令./hadoop fs -ls /xxx查看HDFS文件中xxx目录结构;./hadoop fs -rm /xxx/xxx删除HDFS文件中的xxx文件 ./hadoop fs 基本等同于 ./hdfs dfs 后面直接加相应的命令即可(1.x开头的貌似都是hadoop,2.x开始开始使用hdfs dfs替换hadoop fs。使用的时候就试,hdfs dfs不适用了就回去用hadoop fs)【个人习惯使用./hadoop fs】

4. Zookeeper的常用命令:https://www.cnblogs.com/jifengblog/p/9263817.html 若使用HBase自带的Zookeeper,进入shell使用hbase/bin/hbase zkcli;若使用外置的Zookeeper,进入shell在zookeeper的bin目录下使用 ./zkCli.sh -server localhost:2181。常用命令 ls /xxx查看xxx下的所有子节点;rmr /xxx删除xxx目录;delete /xxx删除xxx节点

5. 修复hbase的时候注意一般的hbck命令都是在线模式修复的,因此无需重启hbase。此处参考https://www.liangzl.com/get-article-detail-19242.html

6. linux终端中将运行结果打印到文本中有三种方法,具体可参考https://blog.csdn.net/zhangping1987/article/details/83179837

这里联想到Linux集群配置SSH的时候将集群中所有节点的密钥追加到同一个文本文档,然后分发到所有的节点实现免密登录。(只要能ping通就算一个小集群)【很多东西用的时候没有注意没有深入思考,等问到的时候还以为自己没见过(之前被问到过linux下如何将程序运行结果打印到日志中,一时卡壳回答不上来简直菜鸡),所以还得多思多想,以问题为索引多多学习多多总结】

7. 排查过程中由于多次使用hbck工具,这个命令使用会分配一个hbase-hbck.lock锁,如果hbck命令正常结束那么锁会自动释放掉,其他命令可以直接使用;但是如果hbck命令被手动终止,那么这个命令无法执行锁也没有释放,其他hbck命令由于无法拿到资源也无法运行,解决方法就是手动删除释放掉这个锁。方法 ./hadoop fs -rm /hbase/.tmp/hbase-hbck.lock

8. 命令有很多,靠脑子记是很容易忘的,所以一个方法是收藏总结比较全面的命令大全博客,另一个方法就是学会使用-help查看支持的相关命令然后根据需要进行选择

9.  几个比较好的HBase维护参考网址:

https://www.sohu.com/a/252429305_315839

http://blog.sina.com.cn/s/blog_7b87efa50102wboj.html

https://blog.csdn.net/yongjian_luo/article/details/53375809

https://www.jianshu.com/p/d5697506741e

另外有的经验教训总结就是有问题先调研分析,确立一个基本的排查思路和备案;排查过程中对于不确定的常用命令,先百度查清楚确定好以后让甲方执行,节约交互时间(不确定不熟悉的东西就要去查,如果是自己一个人那可以去试,但是如果有交互那么要完全确定好后再交互);如果一两天问题还没解决,为了赶紧解决问题不耽误进程并且这个数据并不影响整体就当是坏数据好了,直接暴力删除解决问题。

2.5 删除hbase表问题

运行一个程序,其中一个作用是定期去清理HBase中生命周期大于某些天的表,但是有几个表删除的时候会报错,显示table disabled。

问题分析:2.4的时候为了解决RIT问题暴力disable掉了几张表,于是猜测是这几张表导致报错(系统要删disable状态的表删不掉,就手动删除掉了之前disable的表。

彻底删除表的过程:(暴力方法主要是删除HDFS和Zookeeper下的表信息)

但是发现问题还是存在,于是仔细看了下日志(此处爆锤自己太想当然了)发现是disabled状态的另有其表。本来这个程序就是drop掉表的,不管他是不是disable状态只要把它删除了就成。相比每次根据报错信息取hbase drop掉表或者去HDFS和Zookeeper中rmr表目录而言,修改程序来得更容易也更正确。方法很简单在drop table的相关代码中先判断表是否为disable,是则delete,不是则先disable再delete。

//如果表enabled,则先disable再delete,否则直接delete(已经处于disable状态了直接delete即可)
if(!getHbaseAdmin().isTableDisabled(tableName)){
    //不是disable则先disable
    getHbaseAdmin().disableTable(tableName);
}
    getHbaseAdmin().deleteTable(tableName);

程序边界异常处理真的真的很重要!!!编码的时候多考虑考虑异常处理,让程序更健壮。

总结

学习就是这样吧。看山是山 到 看山不是山 到 看山还是山。路漫漫其修远兮,吾将上下而求索。

明确知识是不可能短时间内学完的,接受任何对于原知识的冲击,及时补充,及时修正,及时跟进,及时记录,相信勤能补拙。

发布了41 篇原创文章 · 获赞 9 · 访问量 9766

猜你喜欢

转载自blog.csdn.net/qq_38586378/article/details/103039136