HBase指南 | HBase 2.0之修復工具HBCK2運維指南
目前社群已經發布了HBase的2.0版本,很多公司都希望去嘗試新版本上的新功能,但是不得不面對的問題就是當叢集出了問題應該如何解決。
在之前的HBase版本中,我們可以依賴hbck來幫助檢查問題和修復問題,在新的版本上我們應該如何去處理呢?HBASE-19121[1]給了我們答案——HBCK2。
HBCK2目前釋出了1.0版本,還在一直開發中,感興趣的同學看看這個issue。
由於之前的hbck(hbck-1)是會直接去向region server或者hdfs傳送請求進行修復,而在HBase 2.0版本上叢集內部操作全部都被挪到了procedure v2(下文都稱為procedure)上進行處理。
因為所有的命令都是經過master來協調處理,所以在修復時也需要通過master進行修復。否則反而可能導致更嚴重的不一致問題。所以hbck-1在HBase-2.x版本是不適用的。
除此以外,很多hbck-1需要處理的問題對於使用procedure的HBase-2.x已經不再是問題了,所以相比起hbck-1來說也精簡了很多功能。

下載:
社群希望把HBase相關的外圍工具抽離出HBase專案,所以在github上建了一個project hbase-operator-tools: hbase-operator-tools[2],HBCK2也在其中
將專案拉取到本地
git clone https://github.com/apache/hbase-operator-tools.git
編譯:
修改pom中依賴的HBase版本 ,實際使用的HBase版本.version>
編譯出jar包
mvn clean package
使用:
cd到HBase目錄下,執行命令:
HBASE_CLASSPATH_PREFIX=
編譯出的hbck2_jar包地址
./bin/hbase org.apache.hbase.HBCK2 <命令>
或者也可以:
./bin/hbase hbck -j <jar包地址> <命令>
由於目前幾乎所有的叢集操作都是通過procedure進行的,所以HBCK2的工作實際就是修復各種不正常的procedure。所以在這裡有必要對procedure進行一個簡單的介紹。
一個procedure是由一系列的操作組成的,一旦完成後,要麼成功,要麼失敗(ROLL BACK), 不存在中間狀態,所以procedure是支援事務的。
procedure執行的每一步都會以log的形式持久化在HBase的MasterProcWals目錄下,這樣master在重啟時也能通過日誌來恢復之前的狀態並且繼續執行。
對於運維而言最重要的一點就是procedure在執行過程中會拿好幾把鎖, 這個在處理問題時是很重要的,因為一旦鎖沒有釋放,再做任何操作也只能是卡住等鎖。
1、IdLock:procedure級別的鎖,保證一個procedure不會被多個執行緒同時執行。
2、資源鎖:對HBase的內部資源進行加鎖,不同的procedure加鎖的粒度不同,目前有region/table/namespace/region server級別的鎖。
舉例來說,假設我assign一個region,那麼procedure在執行的時候就需要對這個region進行加鎖,這樣如果有別的人想要unassign這個region,或者drop這個region所在的table,都需要等最早的assignment結束後釋放鎖了才能執行。這樣防止有不一致的情況出現。

HBCK2的核心功能,bypass可以將一個或多個卡住的procedure進行釋放。
原理很簡單,在procedure的類裡有一個bypass的flag, 每次執行時會檢查這個flag是否為true,如果為true則直接返回null, 這樣procedure就會被認為執行成功。
而我們的bypass就是把這個procedure物件中的這個flag設為true。 這樣stuck的procedure就能夠不再執行,後續的修復工作才能繼續。
返回值為true則是成功,false是失敗。
引數解析:
-o,--overide
在執行bypass之前先會嘗試去拿IdLock, 如果procedure還在執行就會超時返回null,但是設定了這個引數即使拿不到IdLock也會去將procedure的bypass flag設為true。
-r, --recursive
在bypass一個procedure時也會將這個procedure的所有子procedure進行遞迴的bypass。例如我們bypass一個對table schema修改的procedure, 就需要加上-r引數,才能把這個操作的所有子procedure都bypass掉。
-w, --lockWait
上文提到的等待IdLock的超時時間配置,預設為1ms

將一個或多個region再次隨機assign到別的機器上,返回值是建立的pid則為成功,-1則為失敗。
引數解析:
-o,--override
這裡的override跟bypass的override不同,因為assign本身就會建立一個新的procedure, 所以肯定是不涉及到拿IdLock的,但是這裡涉及到資源鎖的問題。因為之前卡住的資源鎖即使在bypass後也不會釋放(用於fence, 防止更多未知的錯誤操作),所以需要加一個-o去手動釋放這個資源鎖。

將一個或多個region unassign,返回值是建立的pid則為成功,-1則為失敗。
引數解析:
-o,--override,與assigns的一致
可能的table狀態, ENABLED, DISABLED, DISABLING, ENABLING
在table的狀態和所有的region狀態不一致時可以用這個命令進行修復

手動schedule一個或多個serverCrashProcedure, 如果有serverCrashProcedure沒有執行成功,但是procedure log已經丟失了,那麼可以利用這個命令進行修復。返回值為建立的pid則為成功,-1則為失敗。
patch在HBASE-21393[3],目前這個功能在release版本還沒有。
所有的武器我們都有了,再回顧一下之前提到的問題,我們應該怎麼處理呢?在Case解決中我們會詳細闡述應該怎麼處理,這裡大家可以先思考一下。

這個章節我們會介紹怎麼去發現目前叢集可能存在的問題。

模擬使用者的讀寫請求,去訪問叢集上的表。當我們需要檢查叢集meta上記錄的region assignment跟實際region server上開啟的region是否一致時,可以使用這個命令去檢查:
hbase canary -f false -t 6000000
這個命令會向meta上的記錄的每個region傳送一個get請求,將-f設為false是為了不在遇到第一個錯誤時退出,-t則是這個命令的超時時間,我們設成了6000秒。在執行完成以後可以通過grep ERROR來找到那些有問題的region。
需要注意的是因為是模擬客戶端傳送的get請求,最好將HBase的客戶端超時時間和超時次數配的小一些,否則會很慢。
PS: canary 本身也很適合用來作為叢集可用性的監控,有興趣的同學可以去了解一下。

其實大部分的資訊都會在master的頁面上展示出來,我們來詳細的介紹一下:
Procedures & Locks:

可以檢查當前所有沒有執行完的procedure以及所有資源鎖,當我們想要assign或者unassign一個region時,需要先去檢查下是由有別的procedure已經佔有了這個資源鎖,如果是的話需要現將那個procedure bypass掉,或者等待那個procedure釋放鎖。

可以看到EXCLUSIVE的lock只有region級別的,圖中紅框圈出來的就是佔有這個鎖的procedure id以及它的parent procedure id, 由此我們知道如果想要重新assign/unassign這個region,那麼一定要bypass這個procedure。
同理,當Locks這塊沒有任何EXLUSIVE鎖時,我們可以放心的去執行操作而不用擔心被卡住。

branch-2.0上最容易出現的問題就是region卡在了OPENNING/CLOSING狀態,一般處於這兩種狀態的region都會在rit的佇列中,可以通過點選頁面上的連結拿到所有的region以及對應的procedure id。

可以看到現在有17個region處在transition中,我們可以點選紅框圈住的這個連結,會展示所有的region。

可以看到現在有17個region處在transition中,我們可以點選紅框圈住的這個連結,會展示所有的region。

因為我們最後是希望通過HBCK2來進行處理,那麼最好是可以複製貼上需要處理的region或者procedure, 所以可以點選圈出的這兩個按鈕,會以text形式展示所有region或者所有procedure。


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
1.region卡在OPENING/CLOSING 狀態
首先找到這些region對應的pid, 然後執行bypass, 檢查是否鎖都釋放了,如果釋放了就再assign一遍,如果需要close,就再unassign一次
2.對table的修改有問題如何回退
找到這個修改的root procedure, bypass -or來bypass所有相關的procedure, 利用table unset來重置meta,因為bypass之後資源鎖還是沒有釋放,所以需要手動加上override引數再去全部assigns一遍
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也會造成這個問題,同樣需要我們去手動assign一下
4.table卡在disabling狀態
因為要求是所有region都disabled, 那麼解決辦法可以是手動把沒有closed的region根據case1來解決。如果所有region都已經是closed狀態了,那麼我可以利用setTableState手動將表的狀態設為DISABLED。之後再drop都是安全的了。

其實HBase-2.x版本的運維思路很簡單,因為使用了procedure,叢集出現meta跟regionserver不一致的狀態是很少的,一般都是有procedure出問題了。那麼我們主要就是看怎麼解決這個有問題的procedure。
如果是table/namespace級別的修改,因為設計到很多region的鎖,如果需要bypass的話需要找到root procedure然後使用bypass -or.
如果只是region級別的問題,則bypass -o即可。
bypass之後檢查locks的頁面,看看是不是鎖都釋放了,如果沒有鎖了則根據需求進行assign或者unassign,或者對table的屬性進行還原。
參考連結:
- [1] ofollow,noindex" target="_blank">https://issues.apache.org/jira/browse/HBASE-19121
- [2] https://github.com/apache/hbase-operator-tools
- [3] https://issues.apache.org/jira/browse/HBASE-21393