HBase2.0的修復(fù)工具HBCK2

1. 背景

在了解HBCK2之前,建議先了解一下啥是HBCK。HBCK是HBase1.x中的命令,到了HBase2.x中,HBCK命令不適用,且它的寫功能(-fix)已刪除,它雖然還可以報告HBase2.x集群的狀態(tài),但是由于它不了解HBase2.x集群內(nèi)部的工作原理,因此其評估將不準(zhǔn)確。因此,如果你正在使用HBase2.x,那么對HBCK2應(yīng)該需要了解一些,即使你不經(jīng)常用到。

2. 獲取HBCK2

HBCK2已經(jīng)被剝離出HBase成為了一個單獨的項目,如果你想要使用這個工具,需要根據(jù)自己HBase的版本,編譯源碼。其GitHub地址為:https://github.com/apache/hbase-operator-tools.git

默認(rèn)HBase的版本是2.1.6,可以在父pom.xml文件里修改成你需要的版本,我們線上集群的版本是cdh-6.3.1-hbase2.1.0,與默認(rèn)版本接近,因此我就使用默認(rèn)的版本。

項目根目錄下運(yùn)行打包命令:


mvn clean install -DskipTests

編譯成功后的截圖:

image-20200527163300460

Base-hbck2的target目錄下可以找到我們最后需要的jar

image-20200527163419002

把該jar包上傳到集群隨便一個目錄下。

3. 測試命令是否可以正常使用

開始使用HBCK2的命令,最直接的使用方式:


./bin/hbase hbck -j <jar包地址> <命令>

使用HBCK2禁用啟用測試表。

運(yùn)行禁用表命令:


hbase hbck -j hbase-hbck2-1.1.0-SNAPSHOT.jar setTableState leo_test DISABLED

  • hbase hbck -j hbase-hbck2-1.1.0-SNAPSHOT.jar 指定jar包的方式使用HBCK2命令

  • setTableState 改變表狀態(tài)的命令

  • leo_test 表名

  • DISABLED 禁用狀態(tài)

看圖,表的狀態(tài)已經(jīng)被更改為DISABLED

image-20200527164346921

運(yùn)行啟用表命令:


hbase hbck -j hbase-hbck2-1.1.0-SNAPSHOT.jar setTableState leo_test ENABLED

看圖,表的狀態(tài)已經(jīng)被更改為ENABLED

image-20200527164512826

有個疑問就是,表狀態(tài)被更改為DISABLED,這張表的region依然是online狀態(tài),表依然可以被正常查詢。

以上操作順利執(zhí)行,就可以證明我們的HBCK2命令被安裝成功了。

4. Procedure簡介

HBase2集群幾乎所有的操作都是通過procedure進(jìn)行的,因此,HBCK2的工作實際就是修復(fù)各種不正常的procedure。

一個procedure是由一系列的操作組成,一旦完成,要么成功,要么失?。≧OLL BACK),不存在中間狀態(tài),所以,procedure是支持事物的。

procedure執(zhí)行的每一步都會以log的形式持久化在HBase的MasterProcWals目錄下,這樣master重啟時也能通過日志來恢復(fù)之前的狀態(tài)且繼續(xù)執(zhí)行。

對于運(yùn)維而言最重要的一點就是procedure在執(zhí)行過程中會拿好幾把鎖, 這個在處理問題時是很重要的,因為一旦鎖沒有釋放,再做任何操作也只能是卡住等鎖。

  • IdLock:procedure級別的鎖,保證一個procedure不會被多個線程同時執(zhí)行。

  • 資源鎖:對HBase的內(nèi)部資源進(jìn)行加鎖,不同的procedure加鎖的粒度不同,目前有region/table/namespace/region server級別的鎖。

舉例來說,假設(shè)我assign一個region,那么procedure在執(zhí)行的時候就需要對這個region進(jìn)行加鎖,這樣如果有別的人想要unassign這個region,或者drop這個region所在的table,都需要等最早的assignment結(jié)束后釋放鎖了才能執(zhí)行。這樣防止有不一致的情況出現(xiàn)。

5. HBCK2核心功能介紹

5.1 bypass [OPTIONS] <PID> ...

bypass可以將一個或多個卡住的procedure進(jìn)行釋放。

原理是,在procedure的類里有一個bypass的flag,每次執(zhí)行時會檢查這個flag是否為true,如果為true則直接返回null,這樣procedure就會被認(rèn)為執(zhí)行成功。

而bypass就是把這個procedure對象中的這個flag設(shè)為true。這樣stuck的procedure就能夠不再執(zhí)行,后續(xù)的修復(fù)才能繼續(xù)。

返回值為true則是成功,false是失敗。

參數(shù)解析:

-o,--overide

在執(zhí)行bypass之前先會嘗試去拿idLock,如果procedure還在運(yùn)行就會超時返回null,但是設(shè)置了這個參數(shù),即使拿不到idLock也會去將procedure的bypass flag設(shè)為true。

-r, --recursive

在bypass一個procedure時也會將這個procedure的所有子procedure進(jìn)行遞歸bypass是。例如我們bypass一個對table schema修改的procedure,就需要加上-r參數(shù),才能把這個操作的所有子procedure都bypass掉。

-w, --lockWait

上面提到的等到idLock的超時時間配置,默認(rèn)為1ms。

5.2 assigns [OPTIONS] <ENCODED_REGIONNAME> ...

將一個或多個region再次隨機(jī)assign到別的機(jī)器上,返回值時創(chuàng)建的pid則為成功,-1則為失敗。

參數(shù)解析:

-o, --override

這里的override跟bypass的override不同,因為assign本身就會創(chuàng)建一個新的procedure,所以肯定是不涉及到拿idLock的,但是這里涉及到資源鎖的問題。因為之前卡住的資源鎖即使在bypass后也不會釋放(用于fence, 防止更多未知的錯誤操作),所以需要加一個-o去手動釋放這個資源鎖。

下面,我們實際運(yùn)行一下這個命令,感受其作用。


hbase hbck -j hbase-hbck2-1.1.0-SNAPSHOT.jar assigns -o leo_test,,1588902855503.596a8c918380a9fb55ed64ecf716ecd6.

  • leo_test,,1588902855503.596a8c918380a9fb55ed64ecf716ecd6. 這個是我測試表,leo_test的一個region的encoded_name

命令執(zhí)行的結(jié)果是:

image-20200527174818532

返回值為-1,說明命令運(yùn)行失敗。

十有八九是我的region name指定錯了,重新運(yùn)行如下命令。


hbase hbck -j hbase-hbck2-1.1.0-SNAPSHOT.jar assigns -o 596a8c918380a9fb55ed64ecf716ecd6

命令執(zhí)行的結(jié)果是:

image-20200527175043176

可以看到,成功返回了此次procedure的ID,觀察HBase自帶的監(jiān)控界面。

image-20200527175200833

HBCK2的命令提交成功后,監(jiān)控界面會顯示此次操作的記錄,里面可以查看命令運(yùn)行的詳細(xì)狀態(tài)。

查看表的監(jiān)控界面,發(fā)現(xiàn)我們操作的region依然在72那臺機(jī)器上,看起來好像沒有任何變化。不知道是不是由于我們測試的表只有一個region的緣故,于是,我又測試了一張有17個region的表。

除了master有這樣的日志之外,還是沒有任何效果。

image-20200527180214854

暫時實在搞不明白這條命令的具體效果,以后再慢慢研究吧,接著來看下一個核心功能。

5.3 unassigns [OPTIONS] <ENCODED_REGIONNAME> ...

將一個或多個region unassign,返回值是創(chuàng)建的pid則為成功,-1則為失敗。

參數(shù)解析:

-o,--override,與assigns的一致

5.4 setTableState <TABLE> <STATE>

可能的table狀態(tài), ENABLED, DISABLED, DISABLING, ENABLING

在table的狀態(tài)和所有的region狀態(tài)不一致時可以用這個命令進(jìn)行修復(fù)

5.5 serverCrashProcedures <ServerName> ...

手動schedule一個或多個serverCrashProcedure, 如果有serverCrashProcedure沒有執(zhí)行成功,但是procedure log已經(jīng)丟失了,那么可以利用這個命令進(jìn)行修復(fù)。返回值為創(chuàng)建的pid則為成功,-1則為失敗。

patch在HBASE-21393[3],目前這個功能在release版本還沒有。

image-20200527181148089

看樣子應(yīng)該能用,可現(xiàn)在就是不知道咋用。

6. 利用HBCK2來查找集群的問題

6.1 canary tool

模擬用戶的讀寫請求,去訪問集群上的表。當(dāng)我們需要檢查集群meta上記錄的region assignment跟實際region server上打開的region是否一致時,可以使用這個命令去檢查:


hbase canary -f false -t 6000000

nohup hbase canary -f false -t 6000000 > /data/leo_jie/hbase.log 2>&1 &

這個命令會向meta上的記錄的每個region發(fā)送一個get請求,將-f設(shè)為false是為了不在遇到第一個錯誤時退出,-t則是這個命令的超時時間,我們設(shè)成了6000秒。在執(zhí)行完成以后可以通過grep ERROR來找到那些有問題的region。

需要注意的是因為是模擬客戶端發(fā)送的get請求,最好將HBase的客戶端超時時間和超時次數(shù)配的小一些,否則會很慢。

PS: canary 本身也很適合用來作為集群可用性的監(jiān)控,有興趣的同學(xué)可以去了解一下。


cat /data/leo_jie/hbase.log | grep ERROR

grep ERROR 來發(fā)現(xiàn)是否有異常信息。

6.2 頁面狀態(tài)

其實大部分的信息都會在master的頁面上展示出來,我們來詳細(xì)的介紹一下:

image-20200527181721474

可以檢查當(dāng)前所有沒有執(zhí)行完的procedure以及所有資源鎖,當(dāng)我們想要assign或者unassign一個region時,需要先去檢查下是由有別的procedure已經(jīng)占有了這個資源鎖,如果是的話需要現(xiàn)將那個procedure bypass掉,或者等待那個procedure釋放鎖。

image

可以看到EXCLUSIVE的lock只有region級別的,圖中紅框圈出來的就是占有這個鎖的procedure id以及它的parent procedure id, 由此我們知道如果想要重新assign/unassign這個region,那么一定要bypass這個procedure。

同理,當(dāng)Locks這塊沒有任何EXLUSIVE鎖時,我們可以放心的去執(zhí)行操作而不用擔(dān)心被卡住。

以上內(nèi)容節(jié)選自,HBase指南 | HBase 2.0之修復(fù)工具HBCK2運(yùn)維指南,因為我在本地測試的時候,沒有重現(xiàn)這種鎖占用的情況。

6.3 OPENING/CLOSING region的查找

branch-2.0 上最容易出現(xiàn)的問題就是region卡在了OPENNING/CLOSING狀態(tài),一般處于這兩種狀態(tài)的region都會在rit的隊列中,可以通過點擊頁面上的鏈接拿到所有的region以及對應(yīng)的procedure id。

image

可以看到現(xiàn)在有17個region處在transition中,我們可以點擊紅框圈住的這個鏈接,會展示所有的region。

image

因為我們最后是希望通過HBCK2來進(jìn)行處理,那么最好是可以復(fù)制粘貼需要處理的region或者procedure, 所以可以點擊圈出的這兩個按鈕,會以text形式展示所有region或者所有procedure。

image

以上內(nèi)容依舊是節(jié)選,因為沒遇到RIT的情況,同時,我們也不希望遇見。??

6.4 Master的日志

stuck的region會打印以下日志:


WARN [ProcExecTimeout] org.apache.hadoop.hbase.master.assignment.AssignmentManager: STUCK Region-In-Transition rit=OPENING, location=c4-hadoop-tst-st99.bj,42900,1542148656901, table=test_modify, region=8d81f74b324d0503c3fc87f34e9a17cb

7.解決問題

定位到問題之后,我們需要解決問題。

7.1 解決region卡在OPENING/CLOSING 狀態(tài)

首先找到這些region對應(yīng)的pid, 然后執(zhí)行bypass, 檢查是否鎖都釋放了,如果釋放了就再assign一遍,如果需要close,就再unassign一次。

7.2 對table的修改有問題如何回退

找到這個修改的root procedure, bypass -or來bypass所有相關(guān)的procedure, 利用table unset來重置meta,因為bypass之后資源鎖還是沒有釋放,所以需要手動加上override參數(shù)再去全部assigns一遍

7.3 Master起不來

日志里一般會有這個:


WARN org.apache.hadoop.hbase.master.HMaster: hbase:meta,,1.1588230740 is NOT online; state={1588230740 state=CLOSING, ts=1538456302300, server=ve1017.example.org,22101,1538449648131}; ServerCrashProcedures=true. Master startup cannot progress, in holding-pattern until region onlined.

手動去assign一下meta表即可,hbase:meta表的encoded name是一個時間戳,比如上面日志的encoded name就是1588230740

另外hbase:namespace表沒有online也會造成這個問題,同樣需要我們?nèi)ナ謩觓ssign一下

7.4 table卡在disabling狀態(tài)

因為要求是所有region都disabled, 那么解決辦法可以是手動把沒有closed的region根據(jù)case1來解決。如果所有region都已經(jīng)是closed狀態(tài)了,那么我可以利用setTableState手動將表的狀態(tài)設(shè)為DISABLED。之后再drop都是安全的了。

8. 總體的解決思路

其實HBase-2.x版本的運(yùn)維思路很簡單,因為使用了procedure,集群出現(xiàn)meta跟regionserver不一致的狀態(tài)是很少的,一般都是有procedure出問題了。那么我們主要就是看怎么解決這個有問題的procedure。

如果是table/namespace級別的修改,因為設(shè)計到很多region的鎖,如果需要bypass的話需要找到root procedure然后使用bypass -or.

如果只是region級別的問題,則bypass -o即可。

bypass之后檢查locks的頁面,看看是不是鎖都釋放了,如果沒有鎖了則根據(jù)需求進(jìn)行assign或者unassign,或者對table的屬性進(jìn)行還原。

9. 參考鏈接

文中很多解決問題的思路參考了一下博客,后續(xù)實踐中如果遇到此類問題,將會進(jìn)行更加詳細(xì)的分析和總結(jié),然后補(bǔ)充文檔。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容