記錄HBase手動刪除Hadoop備份(archive)文件后,引發Hbase寫入數據出錯等一系列問題處理


  由於需要規范HBase數據表命名,對測試環境的數據進行了重命名操作。

  停掉所有服務后執行下面改名操作

# 禁用活躍用戶表
disable 'DC_XXL:ACTIVE_USERS'
# 創建快照
snapshot 'DC_XXL:ACTIVE_USERS', 'tony_snapshot'
# 克隆快照為新的表(使用新名稱)
clone_snapshot 'tony_snapshot', 'DC_XXL:ACTIVE_USERS_LOG'
# 按命名空間查看克隆的表是否存在
list_namespace_tables 'DC_XXL'
# 查看快照
list_snapshots
# 刪除快照
delete_snapshot 'tony_snapshot'
# 查看舊表詳情
desc 'DC_XXL:ACTIVE_USERS' 
# 查看新表詳情,比較兩個表是否一致
desc 'DC_XXL:ACTIVE_USERS_LOG'
# 禁用舊表
disable "DC_XXL:ACTIVE_USERS"
# 刪除舊表
drop 'DC_XXL:ACTIVE_USERS'

  然后重新啟動測試服務。

  操作完后發現測試服務器的存儲空間不足,想要刪除一些數據占用,使用df -h查看各服務器的磁盤空間占用情況,發現Hadoop存儲目錄已占用了90%以上的空間,所以順便使用命令查看一下Hadoop的空間使用情況

# 查看hadoop根目錄各文件夾占用空間
hadoop dfs -du -h /
# 查看hbase占用空間
hadoop dfs -du -h /hbase

  通過命令一層層查看,可以發現主要是hbase占用了存儲,而剛剛執行前面的命令操作后,在hbase目錄下面發現主要存儲空間占用的目錄有:data(項目數據表存儲目錄)與 archive(存檔目錄),而archive目錄一般存儲的是備份用的,理論上來說是可以直接刪除,所以網上查了一些資料說沒問題后,就直接使用 rmr(hadoop dfs -rmr /hbase/archive/data/DC_XXL/ACTIVE_USERS)命令將里面的存檔文件刪除了,沒想到引發了一系列的故障......

  過了一會繼續查看磁盤空間占用,發現磁盤使用在持續快速增長,很快有的服務器已達到100%

  使用 hadoop dfs -du -h /hbase 查看發現,MasterProcWALs 目錄突然間多了幾十G,經查詢這是HBase狀態日志目錄,進去將它們全部刪除,發現磁盤占用還是100%沒有變化

  繼續排查,使用 hadoop dfs -du -h / 發現,原來直接使用rmr刪除后,hadoop會將文件移動到 /user/root/.Trash/Current/hbase/ 這個垃圾站目錄下面

  而這時在查看服務運行日志時,也發現了大量的IO異常

Hbase_thrift.IOError: IOError(message=b'org.apache.hadoop.hbase.client.RetriesExhaustedException: Failed after attempts=16, exceptions:
Mon Jul 06 20:01:52 CST 2020, RpcRetryingCaller{globalStartTime=1594036912662, pause=100, maxAttempts=16}, org.apache.hadoop.hbase.NotServingRegionException: org.apache.hadoop.hbase.NotServingRegionException: DC_XXL:ACTIVE_USERS_LOG,4,1593765189585.73133efd2d876b7f7edabc3ab6709cae. is not online on slave2,16020,1594035938293
    at org.apache.hadoop.hbase.regionserver.HRegionServer.getRegionByEncodedName(HRegionServer.java:3249)
    at org.apache.hadoop.hbase.regionserver.HRegionServer.getRegion(HRegionServer.java:3226)
    at org.apache.hadoop.hbase.regionserver.RSRpcServices.getRegion(RSRpcServices.java:1414)
    at org.apache.hadoop.hbase.regionserver.RSRpcServices.get(RSRpcServices.java:2429)
......

  從日志中可以看到,是由於寫入數據時,所要寫入的region下線所引發的IO異常,在瀏覽器中進入HBase web管理器(http://master:16010),可以看到所有節點都是在線的,拉到 Tables 位置,查看對應的數據表狀態,會發現該表的Other Regions標識了出現問題的數量。

  經過查找資料與思考分析,執行快照操作,HBase會在HDFS中創建一個和unix硬鏈接相同的存儲文件,而執行鏡像克隆操作時,實際上新表與舊表共用相同的數據塊,新表只在data目錄創建新表文件,但並不會復制region,只是通過linkfile定位舊表文件地址。當刪除舊表以后,HBase應該會將舊表數據移動到 archive 目錄下面,只有在新數據寫入並提交compact時,才會數據遷移到新表文件中。所以執行快照和克隆操作是秒級,幾百G的數據執行命令后立馬結果就出來了。

  而我直接刪除了備份文件,數據並沒有遷移完,導致某些region直接丟失了。

  隨后將回收站的文件重新移動到 archive 目錄下面,使用 hbck 命令修復,發現修復失敗,由於是測試數據只需要從kafka中生成最近一周的就可以了,且舊數據占用太多空間需要清理,所以沒有繼續研究修復,直接將它清除,決定創建新表運行相關服務批量重新生成測試數據。

  進入hbase shell中,執行命令

disable 'DC_XXL:ACTIVE_USERS_LOG'

  發現命令卡死,直到超時才退出,發現數據表禁用不了也刪除不了。

  登錄 zookeeper ,刪除對應的數據

# 連接zookeeper服務
/usr/local/zookeeper/bin/zkCli.sh -server master:2181
# 查看hbase數據表
ls /hbase/table
# 刪除數據表
rmr /hbase/table/DC_XXL:ACTIVE_USERS_LOG

  刪除Hadoop存儲的數據

# 查看hadoop的dfs文件
hadoop dfs -du -h /hbase/data/DC_XXL
# 刪除文件
hadoop dfs -rmr /hbase/data/DC_XXL/ACTIVE_USERS_LOG
# 清除垃圾站文件
hadoop dfs -rmr /user/root/.Trash/Current/hbase/data/DC_XXL/ACTIVE_USERS_LOG

  再次進入hbase shell,輸入list已查看不到數據表了,輸入命令創建新表

create 'DC_XXL:ACTIVE_USERS_LOG',{NAME=>'c',COMPRESSION=>'lz4',VERSIONS=>1},SPLITS=>['2','4','6','9']

  這時直接提示:ERROR: Table already exists 異常信息,經過排查發現原來meta表還存儲了數據表以及對應的region信息,需要一一清除干凈才行

# 掃描meta表,查找當前數據表相關記錄
scan 'hbase:meta',{STARTROW=>'DC_XXL:ACTIVE_USERS_LOG',ENDROW=>'DC_XXL:ACTIVE_USERS_LO~'}
# 刪除表記錄命令(這一條命令必須在shell執行,腳本可能刪不干凈)
deleteall 'hbase:meta','DC_XXL:ACTIVE_USERS_LOG'
# 記錄量少的話可以手動一條條刪除
......

  批量刪除 hbase:meta表數據表相關記錄腳本

import happybase

connect = happybase.Connection(host='master', port=9090, timeout=300000, autoconnect=True, compat='0.98', transport='buffered', protocol='binary')

def scan(table, row_prefix=None, columns=None):
    t = happybase.Table(table, connect)
    scan = t.scan(row_prefix=row_prefix, columns=columns)
    data = []
    for key, value in scan:
        result = {row.decode().replace('c:', '').lower(): value[row].decode() for row in value}
        result['pk'] = key.decode()
        data.append(result)
    return data

def delete(table, rowkey):
    t = happybase.Table(table, connect)
    t.delete(rowkey)

if __name__ == '__main__':
    columns = ['info:server']
    row_prefix = 'DC_XXL:ACTIVE_USERS_LOG'.encode()
    result = scan('hbase:meta', row_prefix, columns=columns)
    print(len(result))
    for row in result:
        pk = row.get('pk')
        print(pk)
        delete('hbase:meta', pk)

  腳本執行成功后,需要在shell中執行前面的scan語句檢查一次,看看是否全部都刪除干凈

  然后重啟hbase服務,進入shell中執行創建數據表語句,這次就可以執行成功了(不重啟hbase服務,可能會影響數據表狀態,然后產生大量的異常狀態記錄占用存儲空間)

  

  在這次事件中出現了幾次錯誤操作,導致本次故障。由於之前也試過多次改名,並沒有出現問題,導致本次操作時過於輕心。沒有深入了解快照和克隆快照的底層原理,而網上查到的 archive 相關文章在不了解其背景的情況下,就以為可以直接刪除文件,導致異常的發生。當存儲空間不足時,沒有全面排查了解存儲空間丟失原因,就進行一些處理,導致直接恢復刪除文件並沒有修復問題。而對hbase一些命令的底層運行原理不了解,也造成一些操作上的誤判。好在這只是測試環境,數據丟失影響不大,接下來需要深入研究hbase各方面的運行機制,避免這種低級問題的發生。

 


免責聲明!

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



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