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]);

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM