• HBase2.0 meta信息丢失的修复方法


    在HBase入库日志中发现有一个表入库失败,检查HBase服务端后发现该表的meta信息丢失了:

    而HDFS上的region还在:

    而HBCK工具不支持HBase2.0版本,只好自己写一个修复工具。网上可以搜到前辈们自己编写的一些工具,比如这一篇写的就比较详细 https://blog.csdn.net/xyzkenan/article/details/103476160

    我们引用一下,再对个别地方略微讲解。

    看一下'hbase:meta'中正常的存储结构:

    列名 说明
    info:state Region状态
    info:sn Region Server Node,由 server和serverstartcode组成,如slave1,16020,1557998852385
    info:serverstartcode Region Server启动Code,实质上就是Region Server启动的时间戳
    info:server Region Server 地址和端口,如slave1:16020
    info:seqnumDuringOpen 表示Region在线时长的一个二进制串
    info:regioninfo Region Info,和.regioninfo内容相同

    接下来就开始动手coding:

    获取'hbase:mata'中的Region信息

     1     public Set<String> getMetaRegions(Configuration conf, String tableName) throws Exception {
     2  
     3         Connection conn = ConnectionFactory.createConnection(conf);
     4         Table table = conn.getTable(TableName.valueOf(TABLE));
     5  
     6         PrefixFilter filter = new PrefixFilter(Bytes.toBytes(tableName + ","));
     7  
     8         Scan scan = new Scan();
     9         scan.setFilter(filter);
    10  
    11         Set<String> metaRegions = new HashSet<>();
    12  
    13         Iterator<Result> iterator = table.getScanner(scan).iterator();
    14         while (iterator.hasNext()) {
    15             Result result = iterator.next();
    16             metaRegions.add(Bytes.toString(result.getRow()));
    17         }
    18  
    19         conn.close();
    20  
    21         return metaRegions;
    22     }

    读取.regioninfo中的Region信息

     1     public Map<String, RegionInfo> getHdfsRegions(Configuration conf, String tablePath) throws Exception {
     2  
     3         FileSystem fs = FileSystem.get(conf);
     4         Path path = new Path(hdfsRootDir + "/data/default/" + tablePath + "/");
     5  
     6         Map<String, RegionInfo> hdfsRegions = new HashMap<>();
     7  
     8         FileStatus[] list = fs.listStatus(path);
     9         for (FileStatus status : list) {
    10             if (!status.isDirectory()) {
    11                 continue;
    12             }
    13  
    14             boolean isRegion = false;
    15             FileStatus[] regions = fs.listStatus(status.getPath());
    16             for (FileStatus regionStatus : regions) {
    17                 if (regionStatus.toString().contains(REGION_INFO_FILE)) {
    18                     isRegion = true;
    19                     break;
    20                 }
    21             }
    22  
    23             if (!isRegion) {
    24                 continue;
    25             }
    26  
    27             RegionInfo hri = HRegionFileSystem.loadRegionInfoFileContent(fs, status.getPath());
    28             hdfsRegions.put(hri.getRegionNameAsString(), hri);
    29  
    30         }
    31         return hdfsRegions;
    32     }

    两者进行对比取差集

    1         Set<String> metaRegions = getMetaRegions(configuration, repairTableName);
    2  
    3         Map<String, RegionInfo> hdfsRegions = getHdfsRegions(configuration, repairTableName);
    4  
    5         Set<String> hdfsRegionNames = hdfsRegions.keySet();
    6  
    7         metaRegions.removeAll(hdfsRegionNames);

    构造META信息并写入HBase

     1         ServerName[] regionServers = admin.getRegionServers().toArray(new ServerName[0]);
     2         
     3         int rsLength = regionServers.length;
     4         int i = 0;
     5         for (String regionName : hdfsRegionNames) {
     6  
     7             String sn = regionServers[i % rsLength].getServerName();
     8             String[] snSig = sn.split(",");
     9  
    10             RegionInfo hri = hdfsRegions.get(regionName);
    11             Put info = MetaTableAccessor.makePutFromRegionInfo(hri, EnvironmentEdgeManager.currentTime());
    12             info.addColumn(Bytes.toBytes(FAMILY), Bytes.toBytes(SN), Bytes.toBytes(sn));
    13             info.addColumn(Bytes.toBytes(FAMILY), Bytes.toBytes(SERVER), Bytes.toBytes(snSig[0] + ":" + snSig[1]));
    14             info.addColumn(Bytes.toBytes(FAMILY), Bytes.toBytes(STATE), Bytes.toBytes("OPEN"));
    15  
    16             table.put(info);
    17             i++;
    18         }

    注意这里的各个region是轮流分配给各个regionServers,具体分配可能和meta信息丢失前不同,但是没关系,一个regionServer管理多个region,映射关系可以改变的,重启HBase服务后会生效,HBase内部也会平衡每个regionServer管理的region数量,也可在hbase shell中手动触发平衡。

    使用工具修复后,先验证一下是否生成了新的meta信息:

    确认无误,接下来重启所有HBase服务,重启之后会自动生成'info:seqnumDuringOpen'以及'info:serverstartcode'

    重启之后,验证修复好的表是否可以读写:

    OK,至此基本大功告成,再把工具稍加封装,融入我的组件包内,添加到REST API里,以后再遇到这种问题,发一个POST请求,瞬间修复。

    最后还引用一下前辈封装好的工具以供下载使用,https://github.com/darkphoenixs/hbase-meta-repair

    自己使用时要略加修改,比如你的hbase.root.dir可能不同,此外,我的HBase服务端虽然是2.0,但是我的修复工具使用的是1.x的包,有些接口略有不同,RegionInfo对应的是HRegionInfo,此外,1.x获取RegionServer使用的是

    ServerName[] regionServers = admin.getClusterStatus.getServers().toArray(new ServerName[0]);
  • 相关阅读:
    mvc session验证
    mvc登录验证
    PHP中return的用法
    mvc框架类
    php mvc实现比赛列表
    php MySQLDB类
    php header的几种用法
    php isset()与empty()的使用
    jenkins+springboot+svn linux 自动化部署
    基于netty的websocket例子
  • 原文地址:https://www.cnblogs.com/yudizhao/p/13224863.html
Copyright © 2020-2023  润新知