HBase Meta 元資訊表修復實踐

vivo互联网技术發表於2024-05-11

作者:vivo 網際網路大資料團隊 - Huang Guihu、Chen Shengzun

HBase是一款開源高可靠、高可擴充套件性、高效能的分散式非關係型資料庫,廣泛應用於大資料處理、實時計算、資料儲存和檢索等領域。在分散式叢集中,硬體故障是一種常態,硬體故障可能導致節點或者叢集級別服務中斷、meta表損壞、RIT、Region空洞、重疊等問題,如何快速修復故障恢復業務尤其重要,本文章主要是圍繞HBase meta表常見的故障以及對應解決方案進行描述。

一、背景

相信做過HBase開發、運維相關工作的朋友多多少少都有這樣感受,HBase作為分散式非關係型資料庫中的佼佼者不僅穩定、效能高、安裝擴容等運維也非常簡單,但是HBase缺乏成熟監控系統對故障排查極不友好。如果缺乏對HBase全面瞭解在應對日常故障經常束手無策,小編們作為運維大大小小20+個HBase叢集涉及1.x~2.x等版本,經歷過meta表損壞無法正常上線、Region重疊、Region空洞、許可權丟失等線上問題毒打,也帶著各種各樣問題從HBase原始碼中尋求正確答案,本文是小編們多次故障中總結出的meta表常見解決方案。

二、HBase meta 元資訊表

HBase meta表又稱為catalog表是一張特殊的HBase表,它儲存了HBase叢集所有Region和其對應的RegionServer資訊,元資訊表的資料正確性對於HBase叢集的正常執行至關重要,因此需要保證元資訊表的資料正確是叢集穩定執行的必要條件。如果meta表出現資料不一致將會導致RIT(Region In Transition)甚至出現由於HMaster 無法正常初始化導致叢集無法正常啟動,由此可見meta表在HBase叢集中重要性,下面我們圍繞meta表結構、資料格式、啟動流程進行解析它(本文主要圍繞HBase 2.4.8版本,也會穿插HBase 1.x版本)。

2.1 meta 表結構

meta表主要包括info、table、rep_barrier三個列族分別記錄Region資訊、表狀態:

圖片

2.2 meta 表載入流程

透過上述meta表結構我們對該表有一個整體認識,做過HBase運維的朋友相信都有這種經驗有一些叢集啟動比較快、有一些叢集啟動比較慢,甚至有時候由於操作不當叢集重啟時候一直卡在meta表載入無法繼續執行後續流程。如果我們對meta表載入流程有一個整體瞭解之後我們將對每一個叢集啟動時間多多少少都有一個心理預期,以下是meta表載入相關流程:

圖片

透過以上meta表載入流程圖我們很好找到為什麼有一些叢集啟動比較慢、有一些叢集啟動失敗原因了,下面我們針對兩類場景進行分析:

  • 叢集啟動慢:

通常新叢集或者表數量比較少叢集往往啟動速度比較快,表數量比較多的叢集往往啟動相對慢很多,甚至有一些叢集啟動HMaster需要15~30分鐘,有時候叢集啟動時間比較長讓人不免懷疑是不是叢集出現問題了,為什麼那麼長時間無法進入正常狀態呢?在整個載入流程中出現兩個耗時比較長地方。

預載入所有表描述符:需要把HBase資料目錄全部掃描一遍並解析出.tabledesc目錄下面資料檔案存放HMaster 記憶體中,如果表數量比較多(超過10000張表)這一過程往往需要十來分鐘,如果我們看HMaster 頁面出現“Pre-loading table descriptors”字樣時說明該叢集處於預載入階段我們只需耐心等待即可,因為還沒有到meta表載入階段。

上線業務表Region:meta表資料大小通常在幾十M到幾百M之間Region開啟時間比較快(秒級),叢集啟動階段需要檢查並上線Offline Region,如果想加快開啟速度可以適當調整hbase.master.executor.openregion.threads(預設值為5)值。

  • 叢集啟動失敗:

meta表上線失敗:當default資源組的HRegionServer掛掉之後,重啟後機器的startcode變化之後,meta的資料分片找不到開啟節點,導致叢集啟動失敗。

三、如何修復 meta 表

由於HBase叢集狀態主要是透過meta表去維護,如果meta表出現了損壞或錯誤,將會導致HBase叢集的不可用和麵臨資料丟失風險。我們知道meta表資料一致性非常重要那麼什麼情況會出現資料不一致呢?(HBase 2.4.8修復命令參考hbase-operator-tools工具)。

  • RegionServer當機或異常:當RegionServer當機或異常時,meta表中儲存的Region和RegionServer資訊可能會出現錯誤或丟失。

  • 資料損壞或錯誤:當meta表中的資料損壞或錯誤時,可能會導致HBase叢集的不可用和資料丟失。

  • 非法操作:當對meta表進行非法操作時,例如刪除或修改meta表中的資料,可能會導致meta表出現錯誤或丟失。

meta表故障只是一直比較籠統的說法,我們可以根據型別可以大致分為長時間RIT、Region空洞、Region重疊、表描述檔案丟失、meta表hdfs路徑為空、meta表資料丟失等,下面我分別對這些型別故障進行分析並進行修復:

3.1 RIT

RIT(Region In Transition)是指HBase叢集中正在進行狀態轉換,以下操作都會引起HBase叢集中Region的狀態發生變化,例如RegionServer當機、Region正在進行拆分、合併等操作,Region狀態主要是包括以下十二種狀態以及轉化圖:

圖片

圖片

為了更加清晰Region狀態裝換我們根據操作型別可以分為assign、unassign、split、merge,如果操作過程出現RegionServer當機或異常、資料損壞或錯誤都會出現RIT,RIT雖然是在HBase運維中經常遇見的問題,但是如果清楚底層邏輯將會比較容易處理RIT問題,HBase叢集都具備RIT修復能力大部分情況都不需要手工介入都能正常恢復,出現長時間RIT才需要人工介入處理,那什麼是長時間RIT?為什麼會出現長時間RIT呢?

如果用過HBase 1.x和HBase 2.x版本明顯感覺HBase 2.x比較少出現RIT,其實Region的操作主要是透過AssignmentManager類進行Region轉移,對比兩個版本程式碼我們發現hbase.assignment.maximum.attempts引數(assign重試次數)在兩個版本的預設值不一樣,HBase 2.4.8重試次數為最大整數Integer.MAX_VALUE(而HBase 1.x中該值預設為10),這就是為什麼在HBase 2.x中比較少出現長時間RIT原因。

圖片

RIT處理方法:

  1. 建刪大表都會出現RIT主要是由於Region數量比較多叢集壓力比較大導致assign、unassign響應時間過長導致,針對這類問題一般不需要人工介入HBase可以自愈。

  2. 如果叢集版本為1.x可以適當調整hbase.assignment.maximum.attempts值增加重試次數,如FAILED_OPEN、FAILED_CLOSE通常都可以自愈,或者手工執行assign命令一個個Region分配上線(如果Region比較多切換HMaster 修復)。

  3. 如果出現Region分配失敗,不存在RegionServer時候,手工assign都沒辦法恢復,如Region被分配到bogus.example.com,1,1節點只能透過切換HMaster 恢復。

問題思考:

為什麼Region手工介入都不能正常上線切換HMaster 就能恢復呢?(參考HMaster 啟動流程TransitRegionStateProcedure、HMaster 類原始碼)

3.2 Region 空洞

我們建立HBase表時如果細心去分析Region規律會奇怪發現Region startkey和endkey屬於左閉右開的連續區間,如果突然這些區間少了一塊(如下圖)將會出現什麼問題呢?

圖片

出現上面情況就是我們常說的Region出現空洞,如果用HBase hbck工具檢查會看到這樣錯誤資訊ERROR: There is a hole in the region chain between 01 and 02. You need to create a new .regioninfo and region dir in hdfs to plug the hole,HBase叢集出現空洞往往是沒辦法自愈需要人工干預才能恢復正常,既然我們知道少了一個Region我們如果把空白區間的Region補回去不就可以了嗎?正常做法是先把空白的Region補充回去,並檢查meta表資訊是否正確,最後再上線Region,如果這一系列操作都透過手工去實現不僅僅容易出錯操作時間也很長,下面分別介紹一下不同版本HBase修復方法,其實不同版本處理方法雖然有一點差異但是處理流程都一樣。

圖片

Region空洞處理方法:

(1)HBase 1.x修復方法

  1. HBase hbck –fixHdfsHoles:在hdfs上建立空Region檔案路徑

  2. HBase hbck -fixMeta:修復該Region所在meta表資料

  3. HBase hbck –fixAssignments:上線修復之後Region

  4. 或者HBase hbck –repairHoles相當於(fixHdfsHoles、fixMeta、fixAssignments)幾個組合起來

(2)HBase 2.4.8修復方法(參考後面hbase-operator-tools工具)

由於HBase 2.4.8沒有提供相關的命令去新增Region目錄操作方面相對麻煩一點,其實HBase 2.4.8裡面很多工具類都提供建立Region方法,hbase-server-2.4.8-test包中HBaseTestingUtility類都提供了操作Region相關的入口,下面我們的解決方法主要是圍繞該方法進行恢復。

  1. extraRegionsInMeta -fix:首先把meta表中hdfs目錄不存在記錄先刪除

  2. HBaseTestingUtility.createLocalHRegion:建立hdfs檔案路徑保證Region連續性

  3. addFsRegionsMissingInMeta:再往meta表新增新建Region資訊(新增成功之後會返還Region id

  4. assigns:最後把新加入Region上線

3.3 Region 重疊

既然Region會出現空洞那麼會不會存在這種情況,相同的startkey、endkey出現多個呢?答案是肯定的如果多個Region startkey、endkey是一樣的Region,那麼我們將這種情況稱作Region重疊。Region重疊在HBase中比較難模擬同時也是比較難處理的一種問題。如果我們做hbck檢查時候出現這種日誌ERROR: Multiple regions have the same startkey: 02

圖片

另外一種重疊Region跟相鄰的分片其中一個或兩個的rowkey範圍有交集,這類問題統稱overlap問題,針對這個比較難的場景我們透過自研工具模擬overlap問題復現並一鍵修復overlap(摺疊)和hole(空洞)問題。

overlap問題模擬功能

Region重疊問題實際就是兩個不同Region,rowkey的範圍有交集,比如Region01的startkey和endkey是(01,03),同時另外一個Region02的範圍是(01,02),這樣兩個Region出現了交集(01,02),hbck檢測就會報overlap問題。

重疊問題在生產環境只有在Region分裂和機器同時掛掉情況下,才會出現overlap問題,出現條件比較苛刻,復現問題比較困難,能夠復現問題對後續修復和故障演練都很重要,overlap問題復現原理:

圖片

overlap 問題復現

1)生成一個rowkey範圍重疊的Region分片:

java -jar -Drepair.tableName=migrate:test_hole2 -Dfix.operator=createRegion -DRegion.startkey=06 -DRegion.endkey=07   hbase-meta-tool-0.0.1.jar

2) 將overlap問題Region移動到表目錄下:

sudo -uhdfs hdfs dfs -mv /tmp/.tmp/data/migrate/test_hole2/c8662e08f6ae705237e390029161f58f /hbase/data/migrate/test_hole2

3) 刪除正常的表migrate:test_hole2的meta表資訊:

java -jar -Drepair.tableName=migrate:test_hole2 -Dfix.operator=delete  hbase-meta-tool-0.0.1.jar

4)重構overlap問題表後設資料資訊:

java -jar -Drepair.tableName=migrate:test_hole2 -Dfix.operator=fixFromHdfs  hbase-meta-tool-0.0.1.jar

5) 重啟叢集后hbck報告Region重疊c8662e08f6ae705237e390029161f58f,成功復現重疊問題

圖片

方法一:一鍵修復overlap(重疊)和hole(空洞)

適用於摺疊數量不超過64個情況下,利用自研工具 hbase-meta-tool可以將相鄰Region有rowkey交集的範圍合併,有空洞缺失範圍生成新的Region,這樣就能修復問題,問題修復原理如圖:

圖片

1)修復叢集的重疊與空洞問題:

java -jar  -Dfix.operator= fixOverlapAndHole hbase-meta-tool-0.0.1.jar

方法二:大規模摺疊修復

適用大規模摺疊超過幾千個或者上萬個情況修復伺服器端報異常,採取一下修復手段

1)一鍵清除有摺疊問題表的後設資料:

java -jar -Drepair.tableName=migrate:test1 -Dzookeeper.address=zkAddress -Dfix.operator=delete     hbase-meta-tool-0.0.1.jar

2)備份原始表資料:

hdfs dfs -mv /hbase/data/migrate/test/ /back

3)刪除原始表和匯入備份資料每個Region分片:

hbase org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles /back/test/region01-regionN  migrate:test1

3.4 meta 表資料修復

HBase線上叢集我們可能會遇到下面棘手問題:

  • coprocessor配置錯誤的表,找不到協處理器路徑,載入Region過程中找不到jar,導致叢集反覆掛掉,drop命令也刪除不掉;

  • HBase meta表元數錯誤,startcode不對,上線過程中找不到伺服器的表,表始終不能上線。

我們要在保證不影響叢集其他表服務的情況下,單獨不停服修復問題表。

問題表的meta資料修復

1)假設表migrate:test1有問題,可以一鍵刪除問題表後設資料:

java -jar -Drepair.tableName=migrate:test1 -Dfix.operator=delete  hbase-meta-tool-0.0.1.jar

2)讀取hdfs表的.regioninfo資料夾內容,一鍵重構正確的後設資料:

java -jar -Drepair.tableName=migrate:test1 -Dfix.operator=fixFromHdfs  hbase-meta-tool-0.0.1.jar

3.5 meta 損壞

上述5種情況都是在meta表正常上線的前提下面修復,如果meta表資料損壞無法上線我們應該怎麼修復呢?通常我們都會想到重建meta表再把Region資訊寫入meta表,如果叢集處於下線狀態HBase shell或者HBase api通常是無法執行create建表。

我們分析meta表初始化類InitMetaProcedure發現meta表建立流程大致分兩步走:

1)建立Region目錄已經.tabledesc檔案

2)分配Region並上線。

InitMetaProcedure核心原始碼:

InitMetaProcedure

protected Flow executeFromState(MasterProcedureEnv env, InitMetaState state) throws ProcedureSuspendedException, ProcedureYieldException, InterruptedException {
    try {
      switch (state) {
        case INIT_META_WRITE_FS_LAYOUT:
          Configuration conf = env.getMasterConfiguration();
          Path rootDir = CommonFSUtils.getRootDir(conf);
          TableDescriptor td = writeFsLayout(rootDir, conf);
          env.getMasterServices().getTableDescriptors().update(td, true);
          setNextState(InitMetaState.INIT_META_ASSIGN_META);
          return Flow.HAS_MORE_STATE;
        case INIT_META_ASSIGN_META:
          addChildProcedure(env.getAssignmentManager().createAssignProcedures(Arrays.asList(RegionInfoBuilder.FIRST_META_RegionINFO)));
          return Flow.NO_MORE_STATE;
        default:
          throw new UnsupportedOperationException("unhandled state=" + state);
      }
    } catch (IOException e) {
}
private static TableDescriptor writeFsLayout(Path rootDir, Configuration conf) throws IOException {
    LOG.info("BOOTSTRAP: creating hbase:meta region");
    FileSystem fs = rootDir.getFileSystem(conf);
    Path tableDir = CommonFSUtils.getTableDir(rootDir, TableName.META_TABLE_NAME);
    if (fs.exists(tableDir) && !fs.delete(tableDir, true)) {
      LOG.warn("Can not delete partial created meta table, continue...");
    }
    TableDescriptor metaDescriptor = FSTableDescriptors.tryUpdateAndGetMetaTableDescriptor(conf, fs, rootDir);
    HRegion.createHRegion(RegionInfoBuilder.FIRST_META_RegionINFO, rootDir, conf, metaDescriptor, null).close();
    return metaDescriptor;
}

我們可以參照InitMetaProcedure程式碼邏輯編寫相應工具進行建表上線操作,meta表上線之後我們只需要把每張表Region資訊寫入meta並對所有Region進行assign上線即可恢復叢集正常狀態。透過以上流程我們發現meta表修復流程也並非那麼複雜,但是如果生產環境表數量比較多或者個別大表Region數成千上萬那麼手工新增就變的非常耗時,我們下面介紹一直相對比較簡單的解決方法(HBase 1.x hbck工具、HBase 2.x hbase-operator-tools),下面我們看一下離線修復處理流程。

圖片

HBase 1.x修復方法

  • 停止HBase叢集

  • sudo -u hbase hbase org.apache.hadoop.hbase.util.hbck.OfflineMetaRepair -fix

  • 重啟叢集完成修復。

HBase 2.4.8修復方法(hbase-operator-tools工具)

1)根據hdfs路徑自動生成meta表

  • 停止HBase叢集

  • sudo -u hbase hbase org.apache.hbase.hbck1.OfflineMetaRepair -fix

  • 重啟叢集完成修復。

2)單表修復方法

  • 刪除zookeeper中HBase根目錄

  • 刪除HMaster 、RegionServer所在hdfs WALs目錄

  • 重啟叢集此時meta沒有資料,叢集無法進入正常狀態

  • 執行新增Region命令把hbase:namespace、hbase:quota、hbase:rsgroup、hbase:acl四字表新增到叢集,新增完成之後日誌將會列印assigns後面跟隨這幾張表的Region,需要記錄下這些Region以便下一步assign操作。

sudo -u hbase hbase --config /etc/hbase/conf hbck -j hbase-tools.jar addFsRegionsMissingInMeta hbase:namespace hbase:quota hbase:rsgroup hbase:acl
  • 把上一步新增列印Region上線

sudo -u hbase hbase --config /etc/hbase/conf hbck -j  hbase-hbck2.jar assigns regionid
  • 業務表上線(只需要重複4-5步驟把業務表逐步上線)

注意事項

(如果業務表Region比較多第5不assign不能把Region全部上線成功,需要把表現disable再enable就可以正常上線)

備註:hbase-operator-tools OfflineMetaRepair工具存在以下幾個bug需要修復。

1、HBaseFsck createNewMeta方法建立meta表缺少.tabledesc檔案

修改前:

TableDescriptor td = new FSTableDescriptors(getConf()).get(TableName.META_TABLE_NAME);

修改後:

FileSystem fs = rootdir.getFileSystem(conf);
TableDescriptor metaDescriptor = FSTableDescriptors.tryUpdateAndGetMetaTableDescriptor(getConf(), fs, rootdir);

2、HBaseFsck generatePuts預設Region狀態為CLOSED因為HMaster 重啟時候只上線OFFLINE狀態Region(如果為CLOSED需要手工一個個Region上線工作量非常龐大)

修改前:

addRegionStateToPut(p, org.apache.hadoop.hbase.master.RegionState.State.CLOSED);

修改後:

addRegionStateToPut(p, org.apache.hadoop.hbase.master.RegionState.State.OFFLINE);

缺點

1)離線修復需要停止叢集服務,停止時長根據修復時間而定(大概在10-15分鐘左右)。

2)如果其中存在Region重疊、空洞等問題需要手工處理完成再執行OfflineMetaRepair離線修復命令。

四、hbase-operator-tools工具

hbase-operator-tools是HBase中的一組工具,用於協助HBase管理員管理和維護HBase叢集。hbase-operator-tools提供了一系列工具,包括備份和恢復工具、Region管理工具、資料壓縮和移動工具等,可以幫助管理員更好地管理HBase叢集,提高叢集的穩定性和可靠性。需要編譯原始碼之後才可以使用,原始碼git地址。常見命令如下:

圖片

五、總結

HBase meta表的資料正確性對於HBase叢集的正常執行至關重要,如何保證meta表資料正確以及資料損壞之後快速修復變的極為重要,如果對meta沒有全面認識每次叢集出現故障將會措手無策。本文主要是圍繞meta表結構載入流程、常見問題以及相關的修復方法分析,針對以上修復方法我們可以粗略分為以下兩大類:

  • 線上修復:meta表可以正常透過hbck、自研工具進行meta表資料修復保證資料完整性。

  • 離線修復:meta表無法正常上線根據hdfs中Region資訊重構meta表恢復HBase服務。

如果叢集規模比較大離線修復時間比較長叢集需要長時間停止服務,大部分情況業務是不能容忍可以結合實際情況進行表級別修復(除非meta表檔案損壞不能正常上線),建議定時對叢集做hbck檢查一旦出現元資訊不一致情況儘快修復避免問題擴散(如元信已經錯亂做叢集重啟錯亂Region將會由於assign失敗導致其他Region無法正常上線),如果定時巡檢發現有業務表出現元資訊錯亂情況直接重meta表把該表資訊刪除並根據根據hdfs路徑資訊重新把Region加回meta表(addFsRegions-MissingInMeta命令可以根據hdfs路徑把Region正確新增到meta表)。

參考文章:

  • Apache HBase ™ Reference Guide

  • Apache HBase HBCK2 Tool

  • Appendix C: hbck In Depth

相關文章