• 记录HBase手动删除Hadoop备份(archive)文件后,引发Hbase写入数据出错等一系列问题处理


      由于需要规范HBase数据表命名,对测试环境的数据进行了重命名操作。

      停掉所有服务后执行下面改名操作

    # 禁用活跃用户表
    disable 'DC_XXL:ACTIVE_USERS'
    # 创建快照
    snapshot 'DC_XXL:ACTIVE_USERS', 'tony_snapshot'
    # 克隆快照为新的表(使用新名称)
    clone_snapshot 'tony_snapshot', 'DC_XXL:ACTIVE_USERS_LOG'
    # 按命名空间查看克隆的表是否存在
    list_namespace_tables 'DC_XXL'
    # 查看快照
    list_snapshots
    # 删除快照
    delete_snapshot 'tony_snapshot'
    # 查看旧表详情
    desc 'DC_XXL:ACTIVE_USERS' 
    # 查看新表详情,比较两个表是否一致
    desc 'DC_XXL:ACTIVE_USERS_LOG'
    # 禁用旧表
    disable "DC_XXL:ACTIVE_USERS"
    # 删除旧表
    drop 'DC_XXL:ACTIVE_USERS'

      然后重新启动测试服务。

      操作完后发现测试服务器的存储空间不足,想要删除一些数据占用,使用df -h查看各服务器的磁盘空间占用情况,发现Hadoop存储目录已占用了90%以上的空间,所以顺便使用命令查看一下Hadoop的空间使用情况

    # 查看hadoop根目录各文件夹占用空间
    hadoop dfs -du -h /
    # 查看hbase占用空间
    hadoop dfs -du -h /hbase

      通过命令一层层查看,可以发现主要是hbase占用了存储,而刚刚执行前面的命令操作后,在hbase目录下面发现主要存储空间占用的目录有:data(项目数据表存储目录)与 archive(存档目录),而archive目录一般存储的是备份用的,理论上来说是可以直接删除,所以网上查了一些资料说没问题后,就直接使用 rmr(hadoop dfs -rmr /hbase/archive/data/DC_XXL/ACTIVE_USERS)命令将里面的存档文件删除了,没想到引发了一系列的故障......

      过了一会继续查看磁盘空间占用,发现磁盘使用在持续快速增长,很快有的服务器已达到100%

      使用 hadoop dfs -du -h /hbase 查看发现,MasterProcWALs 目录突然间多了几十G,经查询这是HBase状态日志目录,进去将它们全部删除,发现磁盘占用还是100%没有变化

      继续排查,使用 hadoop dfs -du -h / 发现,原来直接使用rmr删除后,hadoop会将文件移动到 /user/root/.Trash/Current/hbase/ 这个垃圾站目录下面

      而这时在查看服务运行日志时,也发现了大量的IO异常

    Hbase_thrift.IOError: IOError(message=b'org.apache.hadoop.hbase.client.RetriesExhaustedException: Failed after attempts=16, exceptions:
    Mon Jul 06 20:01:52 CST 2020, RpcRetryingCaller{globalStartTime=1594036912662, pause=100, maxAttempts=16}, org.apache.hadoop.hbase.NotServingRegionException: org.apache.hadoop.hbase.NotServingRegionException: DC_XXL:ACTIVE_USERS_LOG,4,1593765189585.73133efd2d876b7f7edabc3ab6709cae. is not online on slave2,16020,1594035938293
        at org.apache.hadoop.hbase.regionserver.HRegionServer.getRegionByEncodedName(HRegionServer.java:3249)
        at org.apache.hadoop.hbase.regionserver.HRegionServer.getRegion(HRegionServer.java:3226)
        at org.apache.hadoop.hbase.regionserver.RSRpcServices.getRegion(RSRpcServices.java:1414)
        at org.apache.hadoop.hbase.regionserver.RSRpcServices.get(RSRpcServices.java:2429)
    ......

      从日志中可以看到,是由于写入数据时,所要写入的region下线所引发的IO异常,在浏览器中进入HBase web管理器(http://master:16010),可以看到所有节点都是在线的,拉到 Tables 位置,查看对应的数据表状态,会发现该表的Other Regions标识了出现问题的数量。

      经过查找资料与思考分析,执行快照操作,HBase会在HDFS中创建一个和unix硬链接相同的存储文件,而执行镜像克隆操作时,实际上新表与旧表共用相同的数据块,新表只在data目录创建新表文件,但并不会复制region,只是通过linkfile定位旧表文件地址。当删除旧表以后,HBase应该会将旧表数据移动到 archive 目录下面,只有在新数据写入并提交compact时,才会数据迁移到新表文件中。所以执行快照和克隆操作是秒级,几百G的数据执行命令后立马结果就出来了。

      而我直接删除了备份文件,数据并没有迁移完,导致某些region直接丢失了。

      随后将回收站的文件重新移动到 archive 目录下面,使用 hbck 命令修复,发现修复失败,由于是测试数据只需要从kafka中生成最近一周的就可以了,且旧数据占用太多空间需要清理,所以没有继续研究修复,直接将它清除,决定创建新表运行相关服务批量重新生成测试数据。

      进入hbase shell中,执行命令

    disable 'DC_XXL:ACTIVE_USERS_LOG'

      发现命令卡死,直到超时才退出,发现数据表禁用不了也删除不了。

      登录 zookeeper ,删除对应的数据

    # 连接zookeeper服务
    /usr/local/zookeeper/bin/zkCli.sh -server master:2181
    # 查看hbase数据表
    ls /hbase/table
    # 删除数据表
    rmr /hbase/table/DC_XXL:ACTIVE_USERS_LOG

      删除Hadoop存储的数据

    # 查看hadoop的dfs文件
    hadoop dfs -du -h /hbase/data/DC_XXL
    # 删除文件
    hadoop dfs -rmr /hbase/data/DC_XXL/ACTIVE_USERS_LOG
    # 清除垃圾站文件
    hadoop dfs -rmr /user/root/.Trash/Current/hbase/data/DC_XXL/ACTIVE_USERS_LOG

      再次进入hbase shell,输入list已查看不到数据表了,输入命令创建新表

    create 'DC_XXL:ACTIVE_USERS_LOG',{NAME=>'c',COMPRESSION=>'lz4',VERSIONS=>1},SPLITS=>['2','4','6','9']

      这时直接提示:ERROR: Table already exists 异常信息,经过排查发现原来meta表还存储了数据表以及对应的region信息,需要一一清除干净才行

    # 扫描meta表,查找当前数据表相关记录
    scan 'hbase:meta',{STARTROW=>'DC_XXL:ACTIVE_USERS_LOG',ENDROW=>'DC_XXL:ACTIVE_USERS_LO~'}
    # 删除表记录命令(这一条命令必须在shell执行,脚本可能删不干净)
    deleteall 'hbase:meta','DC_XXL:ACTIVE_USERS_LOG'
    # 记录量少的话可以手动一条条删除
    ......

      批量删除 hbase:meta表数据表相关记录脚本

    import happybase
    
    connect = happybase.Connection(host='master', port=9090, timeout=300000, autoconnect=True, compat='0.98', transport='buffered', protocol='binary')
    
    def scan(table, row_prefix=None, columns=None):
        t = happybase.Table(table, connect)
        scan = t.scan(row_prefix=row_prefix, columns=columns)
        data = []
        for key, value in scan:
            result = {row.decode().replace('c:', '').lower(): value[row].decode() for row in value}
            result['pk'] = key.decode()
            data.append(result)
        return data
    
    def delete(table, rowkey):
        t = happybase.Table(table, connect)
        t.delete(rowkey)
    
    if __name__ == '__main__':
        columns = ['info:server']
        row_prefix = 'DC_XXL:ACTIVE_USERS_LOG'.encode()
        result = scan('hbase:meta', row_prefix, columns=columns)
        print(len(result))
        for row in result:
            pk = row.get('pk')
            print(pk)
            delete('hbase:meta', pk)

      脚本执行成功后,需要在shell中执行前面的scan语句检查一次,看看是否全部都删除干净

      然后重启hbase服务,进入shell中执行创建数据表语句,这次就可以执行成功了(不重启hbase服务,可能会影响数据表状态,然后产生大量的异常状态记录占用存储空间)

      

      在这次事件中出现了几次错误操作,导致本次故障。由于之前也试过多次改名,并没有出现问题,导致本次操作时过于轻心。没有深入了解快照和克隆快照的底层原理,而网上查到的 archive 相关文章在不了解其背景的情况下,就以为可以直接删除文件,导致异常的发生。当存储空间不足时,没有全面排查了解存储空间丢失原因,就进行一些处理,导致直接恢复删除文件并没有修复问题。而对hbase一些命令的底层运行原理不了解,也造成一些操作上的误判。好在这只是测试环境,数据丢失影响不大,接下来需要深入研究hbase各方面的运行机制,避免这种低级问题的发生。

  • 相关阅读:
    自动安装rpm依赖
    goroutine上下文contxt语法
    goroutine 上下文用法
    Template Method 模式
    设计模式2--设计原则
    centos7关机自动进行远程服务器备份
    实用工具使用
    剑指offer python版 滑动窗口的最大值
    剑指offer python版 左旋转字符串
    剑指offer python版 翻转单词顺序
  • 原文地址:https://www.cnblogs.com/EmptyFS/p/13259995.html
Copyright © 2020-2023  润新知