目录结构
1. 前言java
2. BulkLoad 致使数据无限膨胀node
3. 删表超时致使 RITweb
4. 从新规划 Import 的流程apache
5. 总结centos
1. 前言
Hadoop 集群的 DataNode 节点严重不均衡,某些节点的磁盘空间占用逼近百分之百,眼看着立刻就要爆掉了。bash
虽然这些 DataNode 节点同时也是 HBase 集群的 RegionServer,但一开始还真没把磁盘的这种异常现象与 HBase 的活动联系起来。随后经过查看 HDFS 的日志,咱们才进一步肯定了 HBase 的某一个 RegionServer 此时正发生着大量的写入操做。DataNode 日志信息大体以下:微信

从日志中能够看到,HDFS_WRITE 操做的一个 client id 正指向发生异常的那个 DataNode 节点(也即 RegionServer)。其实,在这段时间内,Hadoop 集群上的大 HBase 集群一直在进行着数据同步操做,线上 HBase 集群的表经过 Export/Import 的方式同步进大 HBase 集群,以后,这个大 HBase 集群将做为灾备集群服务于线上的业务。编辑器
为了提升 Import 阶段 MR 任务的运行效率,咱们改变 Import 时以 HBaseClient 的方式写入集群,而是先用 Import 工具在临时目录中生成每一个表的 HFile,最后再使用 BulkLoad 的方式实现快速的数据导入。然而,一系列异常的情况正是发生在 HFIle BulkLoad 的阶段。函数
2. BulkLoad 致使数据无限膨胀
在肯定是 HBase 的问题以后,咱们重点排查了正在进行的数据同步流程。Import 的 MR 任务完成以后,HFIle 在临时目录中生成。目录中 HFIle 的文件结构以下图所示:工具

接着使用 BulkLoad 的命令快速导入数据,对于数据量比较小的表,命令很快就执行成功了,数据也很快加载完毕,并且数据是完整的,只是让咱们感到奇怪的一点是,BulkLoad 的命令运行结束后,临时目录中生成的 HFIle 一点也没有减小。
在以前 hive to hbase 的数据同步流程中,咱们一样是用 Spark 程序先把 hive 表转换成 HFile,而后用 BulkLoad 的方式导入 HFile,整个流程结束后,临时目录为空,看起来好像是 BulkLoad 的命令作了 Move 操做,把生成的 HFile 直接移动进了 HBase 的数据目录/hbase/data/table
中,整个过程对 HBase 的影响微乎其微。
这两种方式生成的 HFile 究竟有何异同,目前咱们尚未深刻研究,而是放在了以后的计划之中。随后,在继续同步几张数据量比较大的表的时候,BulkLoad 命令执行过程当中打印了以下警告信息:

[2020-07-09 05:23:23,452] {bash_operator.py:120} INFO - 20/07/09 05:23:23 INFO client.RpcRetryingCaller: Call exception, tries=16, retries=35, started=1190177 ms ago, cancelled=false, msg=row 'TMofTtwC4hkHMY6Lq0QKew==' on table 'PERSON_INFO:CELL_PERSON_INFO' at region=PERSON_INFO:CELL_PERSON_INFO,TMofTtwC4hkHMY6Lq0QKew==,1594205285703.24c827308174f7ec321180ff59038072., hostname=rs-host,60020,1594199016949, seqNum=2
[2020-07-09 05:23:23,452] {bash_operator.py:120} INFO - 20/07/09 05:23:23 WARN ipc.CoprocessorRpcChannel: Call failed on IOException
[2020-07-09 05:23:23,453] {bash_operator.py:120} INFO - java.net.SocketTimeoutException: callTimeout=1200000, callDuration=1210221: row 'TMofTtwC4hkHMY6Lq0QKew==' on table 'PERSON_INFO:CELL_PERSON_INFO' at region=PERSON_INFO:CELL_PERSON_INFO,TMofTtwC4hkHMY6Lq0QKew==,1594205285703.24c827308174f7ec321180ff59038072., hostname=rs-host,60020,1594199016949, seqNum=2
[2020-07-09 05:23:23,453] {bash_operator.py:120} INFO - at org.apache.hadoop.hbase.client.RpcRetryingCaller.callWithRetries(RpcRetryingCaller.java:169)
看起来像是 bulkload 超时,而程序依旧在执行,不会被中断,并且这张表的数据目录持续膨胀,原本 100 多 G 的数据,bulkload 命令运行半小时以后,居然膨胀到好几个 T,有些表运行了一夜膨胀到了几十个 T。查看 HBase 的底层数据目录,发现这些表底层 HFile 的存储格式貌似也有些不太正常。

数据表的 hfile 多了好多_Seq 之类的后缀,且这些文件愈来愈多,不知道什么时候才会中止。到了这里,上文描述的某一个 DataNode 磁盘空间占用异常就是这样的文件引发的。对一个 RS 节点产生了这么大影响,当时还觉得是预分区过少或没有给表预分区的缘故,继而致使出现了大量的写入热点。后来又根据表的实际数据量,对表作了从新的预分区操做,可 Import 的过程当中依旧会出现这样的状况。
目前为止,尚未找到一个合理的解释来完美说明为何会出现这样的状况。
3 删表超时致使 RIT
针对那些数据量异常的表,在没找到最合适的解决办法以前,只能优先删除,避免撑爆磁盘。Import 成 HFIle 再 Bulkload 数据的方式,貌似也不太靠谱,只能从新以默认方式进行 Import 操做。
就在删除数据同步过程当中数据量异常的表时,disable 的命令卡在了客户端迟迟没法返回响应结果,最后抛出相似操做超时的异常。在集群监控页面上能够看到 disable 的 Procedures 一直在运行。
disable 的命令卡住:
监控界面上的 disable Procedures 持续在运行:
因为数据量异常的大,disable 的耗时过长,触发了客户端的操做超时,命令自动中断。此时,黔驴技穷了。看起来只能重启集群了,咱们也正是这样作的。而 RIT 正是在此过程当中发生,重启集群的过程当中 CDH 界面上 Master 进程飙红。CDH 的 Master 进程因为 RIT 的存在而没法正常启动。
在 HBase 自带的监控界面上能够看到发生 RIT 的表的信息。
发生 RIT 的表也是上一个删除操做中超时的数据量异常的表,至于 RIT 发生的根本缘由,直至如今也不明其理,只知道上述的种种不正常的操做和表现出来的现象,致使了这个异常。
咱们尝试用hbase hbck
命令来试图修复损坏的 Region。首先运行hbase hbck 待操做表名
的命令来查看当前表的总体状态。并摘取 ERROR 的日志信息。
ERROR: Region { meta => ENTCARD:表名,,1591256713254.77eb283b4525e8ce2f0bcf5d27803927., hdfs => hdfs://hdfs-service/hbase/data/ENTCARD/表名/77eb283b4525e8ce2f0bcf5d27803927, deployed => , replicaId => 0 } not deployed on any region server.
20/07/07 21:57:49 INFO util.HBaseFsck: Handling overlap merges in parallel. set hbasefsck.overlap.merge.parallel to false to run serially.
ERROR: There is a hole in the region chain between and . You need to create a new .regioninfo and region dir in hdfs to plug the hole.
ERROR: Found inconsistency in table ENTCARD:表名
从中进一步获得具体的 ERROR: There is a hole in the region chain between and . You need to create a new .regioninfo and region dir in hdfs to plug the hole 的提示信息,该表出现了 Region 空洞,也就是出现了 start key 和 end key 不连续的 region。
关于 region 空洞的修复,hbase hbck
的使用文档中描述的很详细,运行下 hbase hbck -repairHoles 表名
。
大体说明下该命令的具体做用,也即修复范围。hbase hbck -repairHoles 至关于-fixAssignments -fixMeta -fixHdfsHoles -fixHdfsOrphans 这四个参数同时生效。
-
-fixAssignments 用于修复 Region 分配错误 -
-fixMeta 用于修复.META.表的问题(前提是 HDFS 上的 region 信息是正确的) -
-fixHdfsHoles 修复 RegionHoles 的问题 -
-fixHdfsOrphans 修复 Orphan Region(HDFS 上没有.regioninfo 的 Region
等待命令运行结束后,再一次使用 hbase hbck 待修复的表名
命令来查看集群的状态。在输出信息的末尾,若是你看到一个大大的 OK,那就证实这次修复是成功的,观察 HBase 的集群监控界面,原有 RIT 的错误提示消失不见,集群恢复健康,此时运行重启命令,集群顺利重启,以前超时的 disable 操做的 Procedures 也消失了,而后就能够成功删除那个异常的表了。
异常的表其实有好几张,以后的删除操做中一样遇到了超时卡住的问题和 RIT,针对后续的 RIT,使用hbase hbck 表名
获得的异常信息并不都是 RegionHoles。不同的状态异常以下:
ERROR: Region { meta => person_info:person_info_encrypt,,1591256723291.80e182837f515bfd18c68bd845320875.,
hdfs => hdfs://hdfs-service/hbase/data/person_info/person_info_encrypt/80e182837f515bfd18c68bd845320875,
deployed => centos-bigdata-datanode-ip-.internal,60020,1594127519656;person_info:person_info_encrypt,,1591256723291.80e182837f515bfd18c68bd845320875., replicaId => 0 }
should not be deployed according to META, but is deployed on bigdata-datanode-ip,60020,1594127519656
should not be deployed according to META, but is deployed on 再运行 hbase hbck 的修复命令,提示信息以下:
意思是一个 region close 的关闭任务已经在运行,不能重复提交。
那就只能先重启了,disable 的 Procedures 终止,把这张 RIT 的表直接删掉。
4. 从新规划 Import 的流程
删除掉那些数据量异常的表后,DN 节点的磁盘空间被释放,磁盘的压力也随之消失。原有 Import 成 HFile 再 Bulkload 的方案不能继续用了,只能使用 Import 的默认方式,走 hbase-client API 来写入数据。这种方式写入数据的速度虽然慢,但总不至于引发这样的匪夷所思的异常。
使用 Import 默认的数据导入方式时,还须要注意一个点。对于数据量大的表,建立表时要进行合理的预分区。若是不进行表的预分区操做,数据导入时极大可能会引发写入热点,严重影响数据的读写效率,在极端状况下甚至致使集群的服务挂掉。上述全部操做准备稳当以后,从新调度 Export、Import 的迁移脚本,数据开始稳定导出并写入灾备集群,并且效率也不是很慢。
5. 总结
以上内容林林总总记录了咱们这次跨大版本数据迁移过程当中遇到的种种问题,文字的力量或许还不足以让咱们百分之百重现当时的细枝末节。这里也只是记录了一个大概的过程,中间也遗留了不少亟待解决的问题。
在以往 HBase 的使用经历中,各个场景下的 HBase 的数据迁移,咱们几乎都有碰见过。升级 2.1 时候老 HBase 集群同步数据到新集群,主备新集群之间的数据同步,新集群到大 Hadoop 灾备 HBase 集群间同步数据,HIve 大批量离线数据同步到 HBase 集群等等,所依赖的大部分命令其实都源自 HBase 内置的工具命令。但在具体的实施过程当中,又会遇到各类各样的问题,版本兼容问题,同步效率、稳定性、流程标准化、自动化调度等等。
其实了解一个工具的使用,最简单有效的方式就是深刻源码,在入口函数里你能够找到命令使用的传参细节,在流程代码里你能够剖析工具实现的底层原理,而后是全面而深刻的测试,不要忽略细枝末节,甚至在必要时把源码贴出来进行简单的扩展和包装,最后造成一个标准化的解决流程。
听说,关注个人人都找到了对象👇

本文分享自微信公众号 - HBase工做笔记(HBase-Notes)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。