HBase集群出現(xiàn)NotServingRegionException問題的排查及解決方法
作者: 大圓那些事 | 文章可以轉(zhuǎn)載,請以超鏈接形式標(biāo)明文章原始出處和作者信息
HBase集群在讀寫過程中,可能由于Region Split或Region Blance等導(dǎo)致Region的短暫下線,此時客戶端與HBase集群進(jìn)行RPC操作時會拋出NotServingRegionException異常,從而導(dǎo)致讀寫操作失敗。這里根據(jù)實(shí)際項(xiàng)目經(jīng)驗(yàn),詳細(xì)描述這一問題的發(fā)現(xiàn)及排查解決過程。
1. 發(fā)現(xiàn)問題
在對HBase集群進(jìn)行壓力測試過程中發(fā)現(xiàn),當(dāng)實(shí)際寫入HBase和從HBase查詢的量是平時的若干倍時(集群規(guī)模10~20臺,每秒讀寫數(shù)據(jù)量在幾十萬條記錄的量級),導(dǎo)致集群的讀寫出現(xiàn)一定程度的波動。具體如下:
1)寫端拋出以下異常信息:
|
org.apache.hadoop.hbase.client.RetriesExhaustedWithDetailsException: Failed 150 actions: NotServingRegionException: 150 times, servers with issues: my161208.cm6:60020, at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.processBatchCallback(HConnectionManager.java:1600) at org.apache.hadoop.hbase.client.HConnectionManager$HConnectionImplementation.processBatch(HConnectionManager.java:1376) at org.apache.hadoop.hbase.client.HTable.flushCommits(HTable.java:916) |
2)讀端也拋出類似異常信息:
|
org.apache.hadoop.hbase.client.RetriesExhaustedException: Failed after attempts=10, exceptions: Mon Oct 29 14:03:09 CST 2012, org.apache.hadoop.hbase.client.ScannerCallable@3740fb20, org.apache.hadoop.hbase.NotServingRegionException: org.apache.hadoop.hbase.NotServingRegionException: xxxxxx,\x0FP\x8D\xC3\xDB1053223266:\x00\x00V6,1351490475989.bd68113129f07163dc25e78fba17ad6c. is closing |
以上異常,在壓測期間周期性地出現(xiàn),HBase集群由此出現(xiàn)了短暫的不可服務(wù)期。
2. 排查問題
通過查看HBase Master運(yùn)行日志,結(jié)合客戶端拋出異常的時刻,發(fā)現(xiàn)當(dāng)時HBase集群內(nèi)正在進(jìn)行Region的Split和不同機(jī)器之間的Region Balance,那么,為什么會周期性頻繁觸發(fā)以上過程呢?而且是發(fā)生在壓測期間(數(shù)據(jù)量與平時相比大幾倍)。下面結(jié)合表的設(shè)計來分析一下:
1)由于表中rowkey有時間字段,因此每天都需要新創(chuàng)建Region,同時由于寫入數(shù)據(jù)量大,進(jìn)一步觸發(fā)了HBase的Region Split操作,這一過程一般耗時較長(測試時從線上日志來看,平均為10秒左右,Region大小為4GB),且Region Split操作觸發(fā)較為頻繁;
2)同時由于Region Split操作導(dǎo)致Region分布不均勻,進(jìn)而觸發(fā)HBase自動做Region Balance操作,Region遷移過程中也會導(dǎo)致Region下線,這一過程耗時較長(測試時從線上日志來看,平均為20秒左右)。
3. 解決問題
首先,從客戶端考慮,其實(shí)就是要保證Region下線不可服務(wù)期間,讀寫請求能夠在集群恢復(fù)后繼續(xù),具體可以采取如下措施:
1)對于寫端,可以將未寫入成功的記錄,添加到一個客戶端緩存中,隔一段時間后交給一個后臺線程統(tǒng)一重新提交一次;也可以通過setAutoFlush(flase, false)保證提交失敗的記錄不被拋棄,留在客戶端writeBuffer中等待下次writeBuffer滿了后再次嘗試提交,直到提交成功為止。
2)對于讀端,捕獲異常后,可以采取休眠一段時間后進(jìn)行重試等方式。
3)當(dāng)然,還可以根據(jù)實(shí)際情況合理調(diào)整hbase.client.retries.number和hbase.client.pause配置選項(xiàng)。
然后,從服務(wù)端考慮,需要分別針對Region Split和Region Balance進(jìn)行解決:
1)由于建表時,我們已經(jīng)考慮到了數(shù)據(jù)在不同Region Server上的均勻分布,而且預(yù)先在不同Region Server上創(chuàng)建并分配了相同數(shù)目的Region,那么考慮到為了集群能夠在實(shí)際線上環(huán)境下提供穩(wěn)定的服務(wù),可以選擇關(guān)掉HBase的Region自動Balance功能,當(dāng)然關(guān)掉后可以選擇在每天讀寫壓力小的時候(如凌晨后)觸發(fā)執(zhí)行一次Balance操作即可。
2)接下來,Region總是被創(chuàng)建,不能被復(fù)用的問題該如何解決呢?根本原因是rowkey中包含了timestamp字段,而每時每刻timestamp總是向上增長的。但是,使用方確實(shí)需要能夠根據(jù)timestamp字段進(jìn)行順序scan操作,因此,timestamp字段必須保留。據(jù)此,這里給出兩種解決思路:
- 一種常用方法是將表按照時間分表,例如按天進(jìn)行分表,這樣可以通過預(yù)先建表創(chuàng)建好Region分區(qū),避免實(shí)際讀寫過程中頻繁觸發(fā)Region Split等過程,但是這一方法的缺點(diǎn)是每天需要預(yù)先建好表,而這一DDL過程可能出現(xiàn)問題進(jìn)而導(dǎo)致讀寫出現(xiàn)問題,同時跨天時讀寫端也需要做出適應(yīng),調(diào)整為讀寫新創(chuàng)建的表。
- 其實(shí),我們可以換一種思路,通過修改表的rowkey結(jié)構(gòu),將timestamp字段改成一個周期循環(huán)的timestamp,如取timestamp % TS_MODE后的值,其中TS_MODE須大于等于表的TTL時間周期,這樣才能保證數(shù)據(jù)不會被覆蓋掉。經(jīng)過這樣改造后,即可實(shí)現(xiàn)Region的復(fù)用,避免Region的無限上漲。對于讀寫端的變更也較小,讀寫端操作時只需將timestamp字段取模后作為rowkey進(jìn)行讀寫,另外,讀端需要考慮能適應(yīng)scan掃描時處理[startTsMode, endTsMode]和[endTsMode, startTsMode]兩種情況。
4. 總結(jié)的話
以上僅是本人結(jié)合實(shí)際項(xiàng)目中遇到的問題進(jìn)行了概括總結(jié),僅供參考。歡迎討論交流。
浙公網(wǎng)安備 33010602011771號